Private function to tell if we have RENDER extension.
authorOwen Taylor <otaylor@redhat.com>
Fri, 4 Jan 2002 05:58:01 +0000 (05:58 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Fri, 4 Jan 2002 05:58:01 +0000 (05:58 +0000)
Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>

* gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
(_gdk_x11_have_render): Private function to tell if we have RENDER
extension.

* gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
None if we don't have RENDER extension.

* gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
use Xft unless we have render extension.

* gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
Handle missing render extension.

* gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
gdk/gdkinternals.h: Add a private copy_to_image() virtual function
to the GdkDrawable vtable that extends get_image() to allow
copying onto existing images.  Make the default implementation of
get_image() use this so that backends don't have to implement
both. Add private wrapper _gdk_drawable_copy_to_image().

* gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
copy_to_image() semantics, speed up by using ShmPixmaps and
XCopyArea when possible, XFlush() after ungrabbing the server,
generally redo the logic once again.

* gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
_gdk_windowing_bits_per_depth(): Function to convert from depth to
bits-per-pixel. (We assume only one bpp per depth - X requires
this.)

* gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
scratch image code into a generic _gdk_image_get_scratch() chunk
of code that we can use other places we need scratch images.

* gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
Add _gdk_image_new_for_depth() as the backend
to _gdk_image_new() to allowing creating images with
a depth and no visual.

* gdk/gdkpixbuf-drawable.c: Fix so that getting
parts of images not at 0,0 actually works.

* gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c:
 - Add a new GdkDrawableClass vfunc _draw_pixbuf, and
  _gdk_draw_pixbuf() [ will be made public later ], to allow
  backends to accelerate drawing pixbufs.
 - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
   to be the default implementation.
 - Update docs for gdk_pixbuf_render_to_drawable_alpha().
 - Optimize the default implementation by using
   _gdk_image_copy_to_pixmap() and scratch shared images, and
   special casing the compositing.

* gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
with alpha using the RENDER extension.

        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
Optimize by _gdk_image_copy_to_pixmap() and scratch images.

* tests/testrgb.c: Add test for speed of alpha composition,
reduce the number of iterations since alpha composition
can be a bit slow.

* gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap):
Private function to get a ShmPixmap for an image, if possible.

22 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdkdraw.c
gdk/gdkdrawable.h
gdk/gdkimage.c
gdk/gdkinternals.h
gdk/gdkpixbuf-drawable.c
gdk/gdkpixbuf-render.c
gdk/gdkpixmap.c
gdk/gdkrgb.c
gdk/gdkwindow.c
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkgc-x11.c
gdk/x11/gdkimage-x11.c
gdk/x11/gdkpango-x11.c
gdk/x11/gdkprivate-x11.h
tests/testrgb.c

index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index 287f5a0f8877ba1ef90a3ead39508d574aaf0c4d..be56ec86c7d2610876596f874ffa192ef82c208d 100644 (file)
@@ -1,3 +1,73 @@
+Thu Jan  3 22:18:15 2002  Owen Taylor  <otaylor@redhat.com>
+
+       * gdk/x11/gdkdrawable-x11.c gdk/x11/gdkprivate-x11.h
+       (_gdk_x11_have_render): Private function to tell if we have RENDER
+       extension.
+
+       * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_get_fg_picture): Return
+       None if we don't have RENDER extension.
+
+       * gdk/x11/gdkpango-x11.c (gdk_pango_context_get): Don't
+       use Xft unless we have render extension.
+
+       * gdk/x11/gdkdrawable-x11.c (gdk_x11_drawable_get_picture):
+       Handle missing render extension.
+
+       * gdk/gdkdraw.c gdk/gdkdrawable.h gdk/gdkpixmap.c gdk/gdkwindow.c
+       gdk/gdkinternals.h: Add a private copy_to_image() virtual function
+       to the GdkDrawable vtable that extends get_image() to allow
+       copying onto existing images.  Make the default implementation of
+       get_image() use this so that backends don't have to implement
+       both. Add private wrapper _gdk_drawable_copy_to_image().
+
+       * gdk/x11/gdkimage-x11.c gdk/x11/gdkprivate-x11.c
+       gdk/x11/gdkdrawable-x11.c (_gdk_x11_copy_to_image): Implement
+       copy_to_image() semantics, speed up by using ShmPixmaps and
+       XCopyArea when possible, XFlush() after ungrabbing the server,
+       generally redo the logic once again.
+
+       * gdk/gdkinternals.h gdk/x11/gdkimage-x11.c
+       _gdk_windowing_bits_per_depth(): Function to convert from depth to
+       bits-per-pixel. (We assume only one bpp per depth - X requires
+       this.)
+
+       * gdk/gdkinternals.h gdk/gdkrgb.c gdk/gdkimage.c: Move the GdkRGB
+       scratch image code into a generic _gdk_image_get_scratch() chunk
+       of code that we can use other places we need scratch images.
+
+       * gdk/gdkimage.c gdk/x11/gdkimage.c gdk/gdkinternals.h:
+       Add _gdk_image_new_for_depth() as the backend 
+       to _gdk_image_new() to allowing creating images with
+       a depth and no visual.
+
+       * gdk/gdkpixbuf-drawable.c: Fix so that getting 
+       parts of images not at 0,0 actually works.
+
+       * gdk/gdkdrawable.h gdk/gdkinternals.h gdk/gdkdraw.c
+       gdk/gdkwindow.c gdk/gdkpixmap.c gdk/gdkpixbuf-render.c: 
+        - Add a new GdkDrawableClass vfunc _draw_pixbuf, and 
+         _gdk_draw_pixbuf() [ will be made public later ], to allow 
+         backends to accelerate drawing pixbufs. 
+        - Move the implementation of gdk_pixbuf_render_to_drawable_alpha()
+          to be the default implementation. 
+        - Update docs for gdk_pixbuf_render_to_drawable_alpha(). 
+        - Optimize the default implementation by using 
+          _gdk_image_copy_to_pixmap() and scratch shared images, and
+          special casing the compositing.
+
+       * gdk/x11/gdkdrawable-x11.c: Accelerate _gdk_draw_pixbuf()
+       with alpha using the RENDER extension.
+
+        * gdk/gdkpixbuf-drawable.c (gdk_pixbuf_get_from_drawable):
+       Optimize by _gdk_image_copy_to_pixmap() and scratch images.
+
+       * tests/testrgb.c: Add test for speed of alpha composition,
+       reduce the number of iterations since alpha composition
+       can be a bit slow.
+
+       * gdk/x11/gdkimage-x11.c gdk/gdkprivate-x11.h (_gdk_x11_image_get_shm_pixmap): 
+       Private function to get a ShmPixmap for an image, if possible.
+
 2002-01-04  Anders Carlsson  <andersca@gnu.org>
 
        * tests/testtreesort.c: Add my cool list of integers.
index e2d50121b379c236ed1dd8bf1af4b9a26bf2da74..c7882c577578e27c4353e17faabf93cc6cbd86db 100644 (file)
 #include "gdkdrawable.h"
 #include "gdkinternals.h"
 #include "gdkwindow.h"
-
-static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
-                                                             gint         x,
-                                                             gint         y,
-                                                             gint         width,
-                                                             gint         height,
-                                                             gint        *composite_x_offset,
-                                                             gint        *composite_y_offset);
-static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable *drawable);
+#include "gdk-pixbuf-private.h"
+#include "gdkpixbuf.h"
+
+static GdkImage*    gdk_drawable_real_get_image (GdkDrawable     *drawable,
+                                                gint             x,
+                                                gint             y,
+                                                gint             width,
+                                                gint             height);
+static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable  *drawable,
+                                                             gint          x,
+                                                             gint          y,
+                                                             gint          width,
+                                                             gint          height,
+                                                             gint         *composite_x_offset,
+                                                             gint         *composite_y_offset);
+static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable  *drawable);
+static void         gdk_drawable_real_draw_pixbuf            (GdkDrawable  *drawable,
+                                                             GdkGC        *gc,
+                                                             GdkPixbuf    *pixbuf,
+                                                             gint          src_x,
+                                                             gint          src_y,
+                                                             gint          dest_x,
+                                                             gint          dest_y,
+                                                             gint          width,
+                                                             gint          height,
+                                                             GdkRgbDither  dither,
+                                                             gint          x_dither,
+                                                             gint          y_dither);
 
 static void gdk_drawable_class_init (GdkDrawableClass *klass);
 
@@ -70,10 +89,12 @@ gdk_drawable_get_type (void)
 static void
 gdk_drawable_class_init (GdkDrawableClass *klass)
 {
+  klass->get_image = gdk_drawable_real_get_image;
   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
   /* Default implementation for clip and visible region is the same */
   klass->get_clip_region = gdk_drawable_real_get_visible_region;
   klass->get_visible_region = gdk_drawable_real_get_visible_region;
+  klass->_draw_pixbuf = gdk_drawable_real_draw_pixbuf;
 }
 
 /* Manipulation of drawables
@@ -529,6 +550,57 @@ gdk_draw_image (GdkDrawable *drawable,
                                                  xdest, ydest, width, height);
 }
 
+/**
+ * _gdk_draw_pixbuf:
+ * @drawable: Destination drawable.
+ * @gc: a #GdkGC, used for clipping, or %NULL
+ * @pixbuf: a #GdkPixbuf
+ * @src_x: Source X coordinate within pixbuf.
+ * @src_y: Source Y coordinates within pixbuf.
+ * @dest_x: Destination X coordinate within drawable.
+ * @dest_y: Destination Y coordinate within drawable.
+ * @width: Width of region to render, in pixels, or -1 to use pixbuf width.
+ * @height: Height of region to render, in pixels, or -1 to use pixbuf height.
+ * @dither: Dithering mode for GdkRGB.
+ * @x_dither: X offset for dither.
+ * @y_dither: Y offset for dither.
+ * 
+ * Renders a rectangular portion of a pixbuf to a drawable.  The destination
+ * drawable must have a colormap. All windows have a colormap, however, pixmaps
+ * only have colormap by default if they were created with a non-NULL window argument.
+ * Otherwise a colormap must be set on them with gdk_drawable_set_colormap.
+ *
+ * On older X servers, rendering pixbufs with an alpha channel involves round trips
+ * to the X server, and may be somewhat slow.
+ **/
+void
+_gdk_draw_pixbuf (GdkDrawable     *drawable,
+                 GdkGC           *gc,
+                 GdkPixbuf       *pixbuf,
+                 gint             src_x,
+                 gint             src_y,
+                 gint             dest_x,
+                 gint             dest_y,
+                 gint             width,
+                 gint             height,
+                 GdkRgbDither     dither,
+                 gint             x_dither,
+                 gint             y_dither)
+{
+  g_return_if_fail (GDK_IS_DRAWABLE (drawable));
+  g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
+  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+
+  if (width == -1)
+    width = gdk_pixbuf_get_width (pixbuf);
+  if (height == -1)
+    height = gdk_pixbuf_get_height (pixbuf);
+
+  GDK_DRAWABLE_GET_CLASS (drawable)->_draw_pixbuf (drawable, gc, pixbuf,
+                                                  src_x, src_y, dest_x, dest_y, width, height,
+                                                  dither, x_dither, y_dither);
+}
+
 void
 gdk_draw_points (GdkDrawable *drawable,
                 GdkGC       *gc,
@@ -617,6 +689,80 @@ gdk_draw_glyphs (GdkDrawable      *drawable,
 }
 
 
+/**
+ * _gdk_drawable_copy_to_image:
+ * @drawable: a #GdkDrawable
+ * @image: a #GdkDrawable, or %NULL if a new @image should be created.
+ * @src_x: x coordinate on @drawable
+ * @src_y: y coordinate on @drawable
+ * @dest_x: x coordinate within @image. Must be 0 if @image is %NULL
+ * @dest_y: y coordinate within @image. Must be 0 if @image is %NULL
+ * @width: width of region to get
+ * @height: height or region to get
+ *
+ * Copies a portion of @drawable into the client side image structure
+ * @image. If @image is %NULL, creates a new image of size @width x @height
+ * and copies into that. See gdk_drawable_get_image() for further details.
+ * 
+ * Return value: @image, or a new a #GdkImage containing the contents
+                 of @drawable
+ **/
+GdkImage*
+_gdk_drawable_copy_to_image (GdkDrawable *drawable,
+                            GdkImage    *image,
+                            gint         src_x,
+                            gint         src_y,
+                            gint         dest_x,
+                            gint         dest_y,
+                            gint         width,
+                            gint         height)
+{
+  GdkDrawable *composite;
+  gint composite_x_offset = 0;
+  gint composite_y_offset = 0;
+  GdkImage *retval;
+  GdkColormap *cmap;
+  
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+  g_return_val_if_fail (src_x >= 0, NULL);
+  g_return_val_if_fail (src_y >= 0, NULL);
+
+  /* FIXME? Note race condition since we get the size then
+   * get the image, and the size may have changed.
+   */
+  
+  if (width < 0 || height < 0)
+    gdk_drawable_get_size (drawable,
+                           width < 0 ? &width : NULL,
+                           height < 0 ? &height : NULL);
+  
+  composite =
+    GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
+                                                               src_x, src_y,
+                                                               width, height,
+                                                               &composite_x_offset,
+                                                               &composite_y_offset); 
+  
+  retval = GDK_DRAWABLE_GET_CLASS (composite)->_copy_to_image (composite,
+                                                              image,
+                                                              src_x - composite_x_offset,
+                                                              src_y - composite_y_offset,
+                                                              dest_x, dest_y,
+                                                              width, height);
+
+  g_object_unref (G_OBJECT (composite));
+
+  if (!image && retval)
+    {
+      cmap = gdk_drawable_get_colormap (drawable);
+      
+      if (cmap)
+       gdk_image_set_colormap (retval, cmap);
+    }
+  
+  return retval;
+}
+
 /**
  * gdk_drawable_get_image:
  * @drawable: a #GdkDrawable
@@ -705,6 +851,16 @@ gdk_drawable_get_image (GdkDrawable *drawable,
   return retval;
 }
 
+static GdkImage*
+gdk_drawable_real_get_image (GdkDrawable     *drawable,
+                            gint             x,
+                            gint             y,
+                            gint             width,
+                            gint             height)
+{
+  return _gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
+}
+
 static GdkDrawable*
 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
                                           gint         x,
@@ -776,3 +932,386 @@ gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
 
   return gdk_region_rectangle (&rect);
 }
+
+static void
+composite (guchar *src_buf,
+          gint    src_rowstride,
+          guchar *dest_buf,
+          gint    dest_rowstride,
+          gint    width,
+          gint    height)
+{
+  guchar *src = src_buf;
+  guchar *dest = dest_buf;
+
+  while (height--)
+    {
+      gint twidth = width;
+      guchar *p = src;
+      guchar *q = dest;
+
+      while (twidth--)
+       {
+         guchar a = p[3];
+         guint t;
+
+         t = a * p[0] + (255 - a) * q[0] + 0x80;
+         q[0] = (t + (t >> 8)) >> 8;
+         t = a * p[1] + (255 - a) * q[1] + 0x80;
+         q[1] = (t + (t >> 8)) >> 8;
+         t = a * p[2] + (255 - a) * q[2] + 0x80;
+         q[2] = (t + (t >> 8)) >> 8;
+
+         p += 4;
+         q += 3;
+       }
+      
+      src += src_rowstride;
+      dest += dest_rowstride;
+    }
+}
+
+static void
+composite_0888 (guchar      *src_buf,
+               gint         src_rowstride,
+               guchar      *dest_buf,
+               gint         dest_rowstride,
+               GdkByteOrder dest_byte_order,
+               gint         width,
+               gint         height)
+{
+  guchar *src = src_buf;
+  guchar *dest = dest_buf;
+
+  while (height--)
+    {
+      gint twidth = width;
+      guchar *p = src;
+      guchar *q = dest;
+
+      if (dest_byte_order == GDK_LSB_FIRST)
+       {
+         while (twidth--)
+           {
+             guint t;
+             
+             t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
+             q[0] = (t + (t >> 8)) >> 8;
+             t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
+             q[1] = (t + (t >> 8)) >> 8;
+             t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
+             q[2] = (t + (t >> 8)) >> 8;
+             p += 4;
+             q += 4;
+           }
+       }
+      else
+       {
+         while (twidth--)
+           {
+             guint t;
+             
+             t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
+             q[1] = (t + (t >> 8)) >> 8;
+             t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
+             q[2] = (t + (t >> 8)) >> 8;
+             t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
+             q[3] = (t + (t >> 8)) >> 8;
+             p += 4;
+             q += 4;
+           }
+       }
+      
+      src += src_rowstride;
+      dest += dest_rowstride;
+    }
+}
+
+static void
+composite_565 (guchar      *src_buf,
+              gint         src_rowstride,
+              guchar      *dest_buf,
+              gint         dest_rowstride,
+              GdkByteOrder dest_byte_order,
+              gint         width,
+              gint         height)
+{
+  guchar *src = src_buf;
+  guchar *dest = dest_buf;
+
+  while (height--)
+    {
+      gint twidth = width;
+      guchar *p = src;
+      gushort *q = (gushort *)dest;
+
+      while (twidth--)
+       {
+         guchar a = p[3];
+         guint tr, tg, tb;
+         guint tr1, tg1, tb1;
+         guint tmp = *q;
+
+#if 1
+         /* This is fast, and corresponds to what composite() above does
+          * if we converted to 8-bit first.
+          */
+         tr = (tmp & 0xf800);
+         tr1 = a * p[0] + (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
+         tg = (tmp & 0x07e0);
+         tg1 = a * p[1] + (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
+         tb = (tmp & 0x001f);
+         tb1 = a * p[2] + (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
+
+         *q = (((tr1 + (tr1 >> 8)) & 0xf800) |
+               (((tg1 + (tg1 >> 8)) & 0xfc00) >> 5)  |
+               ((tb1 + (tb1 >> 8)) >> 11));
+#else
+         /* This version correspond to the result we get with XRENDER -
+          * a bit of precision is lost since we convert to 8 bit after premultiplying
+          * instead of at the end
+          */
+         guint tr2, tg2, tb2;
+         guint tr3, tg3, tb3;
+         
+         tr = (tmp & 0xf800);
+         tr1 = (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
+         tr2 = a * p[0] + 0x80;
+         tr3 = ((tr1 + (tr1 >> 8)) >> 8) + ((tr2 + (tr2 >> 8)) >> 8);
+
+         tg = (tmp & 0x07e0);
+         tg1 = (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
+         tg2 = a * p[0] + 0x80;
+         tg3 = ((tg1 + (tg1 >> 8)) >> 8) + ((tg2 + (tg2 >> 8)) >> 8);
+
+         tb = (tmp & 0x001f);
+         tb1 = (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
+         tb2 = a * p[0] + 0x80;
+         tb3 = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
+
+         *q = (((tr3 & 0xf8) << 8) |
+               ((tg3 & 0xfc) << 3) |
+               ((tb3 >> 3)));
+#endif
+         
+         p += 4;
+         q++;
+       }
+      
+      src += src_rowstride;
+      dest += dest_rowstride;
+    }
+}
+
+static void
+gdk_drawable_real_draw_pixbuf (GdkDrawable  *drawable,
+                              GdkGC        *gc,
+                              GdkPixbuf    *pixbuf,
+                              gint          src_x,
+                              gint          src_y,
+                              gint          dest_x,
+                              gint          dest_y,
+                              gint          width,
+                              gint          height,
+                              GdkRgbDither  dither,
+                              gint          x_dither,
+                              gint          y_dither)
+{
+  gboolean free_gc = FALSE;
+  GdkPixbuf *composited = NULL;
+  gint dwidth, dheight;
+  GdkRegion *clip;
+  GdkRegion *drect;
+  GdkRectangle tmp_rect;
+                                      
+  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
+  g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
+  g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
+  g_return_if_fail (pixbuf->bits_per_sample == 8);
+
+  g_return_if_fail (drawable != NULL);
+
+  if (width == -1) 
+    width = pixbuf->width;
+  if (height == -1)
+    height = pixbuf->height;
+
+  g_return_if_fail (width >= 0 && height >= 0);
+  g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
+  g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
+
+  /* Clip to the drawable; this is required for get_from_drawable() so
+   * can't be done implicitly
+   */
+  
+  if (dest_x < 0)
+    {
+      src_x -= dest_x;
+      width += dest_x;
+      dest_x = 0;
+    }
+
+  if (dest_y < 0)
+    {
+      src_y -= dest_y;
+      height += dest_y;
+      dest_y = 0;
+    }
+
+  gdk_drawable_get_size (drawable, &dwidth, &dheight);
+
+  if ((dest_x + width) > dwidth)
+    width = dwidth - dest_x;
+
+  if ((dest_y + height) > dheight)
+    height = dheight - dest_y;
+
+  if (width <= 0 || height <= 0)
+    return;
+
+  /* Clip to the clip region; this avoids getting more
+   * image data from the server than we need to.
+   */
+  
+  tmp_rect.x = dest_x;
+  tmp_rect.y = dest_y;
+  tmp_rect.width = width;
+  tmp_rect.height = height;
+
+  drect = gdk_region_rectangle (&tmp_rect);
+  clip = gdk_drawable_get_clip_region (drawable);
+
+  gdk_region_intersect (drect, clip);
+
+  gdk_region_get_clipbox (drect, &tmp_rect);
+  
+  gdk_region_destroy (drect);
+  gdk_region_destroy (clip);
+
+  if (tmp_rect.width == 0 ||
+      tmp_rect.height == 0)
+    return;
+  
+  /* Actually draw */
+
+  if (!gc)
+    {
+      gc = gdk_gc_new (drawable);
+      free_gc = TRUE;
+    }
+  
+  if (pixbuf->has_alpha)
+    {
+      GdkVisual *visual = gdk_drawable_get_visual (drawable);
+      void (*composite_func) (guchar       *src_buf,
+                             gint          src_rowstride,
+                             guchar       *dest_buf,
+                             gint          dest_rowstride,
+                             GdkByteOrder  dest_byte_order,
+                             gint          width,
+                             gint          height) = NULL;
+
+      /* First we see if we have a visual-specific composition function that can composite
+       * the pixbuf data directly onto the image
+       */
+      if (visual)
+       {
+         gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (visual->depth);
+         
+         if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
+             visual->depth == 16 &&
+             visual->red_mask   == 0xf800 &&
+             visual->green_mask == 0x07e0 &&
+             visual->blue_mask  == 0x001f)
+           composite_func = composite_565;
+         else if (visual->depth == 24 && bits_per_pixel == 32 &&
+                  visual->red_mask   == 0xff0000 &&
+                  visual->green_mask == 0x00ff00 &&
+                  visual->blue_mask  == 0x0000ff)
+           composite_func = composite_0888;
+       }
+
+      /* We can't use our composite func if we are required to dither
+       */
+      if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
+       {
+         gint x0, y0;
+         for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
+           {
+             gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
+             for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
+               {
+                 gint xs0, ys0;
+                 
+                 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
+                 
+                 GdkImage *image = _gdk_image_get_scratch (width1, height1, gdk_drawable_get_depth (drawable), &xs0, &ys0);
+                 
+                 _gdk_drawable_copy_to_image (drawable, image,
+                                              dest_x + x0, dest_y + y0,
+                                              xs0, ys0,
+                                              width1, height1);
+                 (*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4,
+                                    pixbuf->rowstride,
+                                    image->mem + ys0 * image->bpl + xs0 * image->bpp,
+                                    image->bpl,
+                                    visual->byte_order,
+                                    width1, height1);
+                 gdk_draw_image (drawable, gc, image,
+                                 xs0, ys0,
+                                 dest_x + x0, dest_y + y0,
+                                 width1, height1);
+               }
+           }
+         
+         goto out;
+       }
+      else
+       {
+         /* No special composition func, convert dest to 24 bit RGB data, composite against
+          * that, and convert back.
+          */
+         composited = gdk_pixbuf_get_from_drawable (NULL,
+                                                    drawable,
+                                                    NULL,
+                                                    dest_x, dest_y,
+                                                    0, 0,
+                                                    width, height);
+         
+         if (composited)
+           composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
+                      pixbuf->rowstride,
+                      composited->pixels,
+                      composited->rowstride,
+                      width, height);
+       }
+    }
+
+  if (composited)
+    {
+      gdk_pixbuf_render_to_drawable (composited,
+                                     drawable, gc,
+                                     0, 0,
+                                     dest_x, dest_y,
+                                     width, height,
+                                     dither,
+                                     x_dither, y_dither);
+    }
+  else
+    {
+      gdk_pixbuf_render_to_drawable (pixbuf,
+                                     drawable, gc,
+                                     src_x, src_y,
+                                     dest_x, dest_y,
+                                     width, height,
+                                     dither,
+                                     x_dither, y_dither);
+    }
+
+ out:
+  if (composited)
+    g_object_unref (G_OBJECT (composited));
+
+  if (free_gc)
+    gdk_gc_unref (gc);
+}
index e343d8ae62e10f445ef846f8b535eb913afdb7c9..6d2d4d9b7bf9a2c8a9e3a8ea5a83eaf6cca0d727 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <gdk/gdktypes.h>
 #include <gdk/gdkgc.h>
+#include <gdk/gdkrgb.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -130,7 +132,28 @@ struct _GdkDrawableClass
                                           gint         height,
                                           gint        *composite_x_offset,
                                           gint        *composite_y_offset);
-  
+
+  void         (*_draw_pixbuf) (GdkDrawable *drawable,
+                               GdkGC       *gc,
+                               GdkPixbuf   *pixbuf,
+                               gint         src_x,
+                               gint         src_y,
+                               gint         dest_x,
+                               gint         dest_y,
+                               gint         width,
+                               gint         height,
+                               GdkRgbDither dither,
+                               gint         x_dither,
+                               gint         y_dither);
+  GdkImage*    (*_copy_to_image) (GdkDrawable    *drawable,
+                                 GdkImage       *image,
+                                 gint            src_x,
+                                 gint            src_y,
+                                 gint            dest_x,
+                                 gint            dest_y,
+                                 gint            width,
+                                 gint            height);
+
   void         (*_gdk_reserved1) (void);
   void         (*_gdk_reserved2) (void);
   void         (*_gdk_reserved3) (void);
index fe913325fa7cd4dece8dc04c150e404984611f23..e748d8f52710e7516d253e2137f151ec57427de2 100644 (file)
 #include <stdlib.h>
 #include <sys/types.h>
 
+#include "gdk.h"               /* For gdk_flush() */
 #include "gdkimage.h"
 #include "gdkprivate.h"
+#include "gdkinternals.h"      /* For scratch_image code */
 
 /**
  * gdk_image_ref:
@@ -137,3 +139,264 @@ gdk_image_get_colormap (GdkImage *image)
 
   return image->colormap;
 }
+
+/* We have N_REGION GDK_SCRATCH_IMAGE_WIDTH x GDK_SCRATCH_IMAGE_HEIGHT regions divided
+ * up between n_images different images. possible_n_images gives
+ * various divisors of N_REGIONS. The reason for allowing this
+ * flexibility is that we want to create as few images as possible,
+ * but we want to deal with the abberant systems that have a SHMMAX
+ * limit less than
+ *
+ * GDK_SCRATCH_IMAGE_WIDTH * GDK_SCRATCH_IMAGE_HEIGHT * N_REGIONS * 4 (384k)
+ *
+ * (Are there any such?)
+ */
+#define N_REGIONS 6
+static const int possible_n_images[] = { 1, 2, 3, 6 };
+
+/* We allocate one GdkScratchImageInfo structure for each
+ * depth where we are allocating scratch images. (Future: one
+ * per depth, per display)
+ */
+typedef struct _GdkScratchImageInfo GdkScratchImageInfo;
+
+struct _GdkScratchImageInfo {
+  gint depth;
+  
+  gint n_images;
+  GdkImage *static_image[N_REGIONS];
+  gint static_image_idx;
+
+  /* In order to optimize filling fractions, we simultaneously fill in up
+   * to three regions of size GDK_SCRATCH_IMAGE_WIDTH * GDK_SCRATCH_IMAGE_HEIGHT: one
+   * for images that are taller than GDK_SCRATCH_IMAGE_HEIGHT / 2, and must
+   * be tiled horizontally. One for images that are wider than
+   * GDK_SCRATCH_IMAGE_WIDTH / 2 and must be tiled vertically, and a third
+   * for images smaller than GDK_SCRATCH_IMAGE_HEIGHT / 2 x GDK_SCRATCH_IMAGE_WIDTH x 2
+   * that we tile in horizontal rows.
+   */
+  gint horiz_idx;
+  gint horiz_y;
+  gint vert_idx;
+  gint vert_x;
+  
+  /* tile_y1 and tile_y2 define the horizontal band into
+   * which we are tiling images. tile_x is the x extent to
+   * which that is filled
+   */
+  gint tile_idx;
+  gint tile_x;
+  gint tile_y1;
+  gint tile_y2;
+};
+
+static GSList *scratch_image_infos = NULL;
+
+static gboolean
+allocate_scratch_images (GdkScratchImageInfo *info,
+                        gint                 n_images,
+                        gboolean             shared)
+{
+  gint i;
+  
+  for (i = 0; i < n_images; i++)
+    {
+      info->static_image[i] = _gdk_image_new_for_depth (shared ? GDK_IMAGE_SHARED : GDK_IMAGE_NORMAL,
+                                                       NULL,
+                                                       GDK_SCRATCH_IMAGE_WIDTH * (N_REGIONS / n_images), GDK_SCRATCH_IMAGE_HEIGHT,
+                                                       info->depth);
+      
+      if (!info->static_image[i])
+       {
+         gint j;
+         
+         for (j = 0; j < i; j++)
+           gdk_image_unref (info->static_image[i]);
+         
+         return FALSE;
+       }
+    }
+  
+  return TRUE;
+}
+
+GdkScratchImageInfo *
+scratch_image_info_for_depth (gint depth)
+{
+  GSList *tmp_list;
+  GdkScratchImageInfo *image_info;
+  gint i;
+
+  tmp_list = scratch_image_infos;
+  while (tmp_list)
+    {
+      image_info = tmp_list->data;
+      if (image_info->depth == depth)
+       return image_info;
+      
+      tmp_list = tmp_list->next;
+    }
+
+  image_info = g_new (GdkScratchImageInfo, 1);
+
+  image_info->depth = depth;
+
+    /* Try to allocate as few possible shared images */
+  for (i=0; i < G_N_ELEMENTS (possible_n_images); i++)
+    {
+      if (allocate_scratch_images (image_info, possible_n_images[i], TRUE))
+       {
+         image_info->n_images = possible_n_images[i];
+         break;
+       }
+    }
+
+  /* If that fails, just allocate N_REGIONS normal images */
+  if (i == G_N_ELEMENTS (possible_n_images))
+    {
+      allocate_scratch_images (image_info, N_REGIONS, FALSE);
+      image_info->n_images = N_REGIONS;
+    }
+
+  image_info->static_image_idx = 0;
+
+  image_info->horiz_y = GDK_SCRATCH_IMAGE_HEIGHT;
+  image_info->vert_x = GDK_SCRATCH_IMAGE_WIDTH;
+  image_info->tile_x = GDK_SCRATCH_IMAGE_WIDTH;
+  image_info->tile_y1 = image_info->tile_y2 = GDK_SCRATCH_IMAGE_HEIGHT;
+
+  scratch_image_infos = g_slist_prepend (scratch_image_infos, image_info);
+
+  return image_info;
+}
+
+/* Defining NO_FLUSH can cause inconsistent screen updates, but is useful
+   for performance evaluation. */
+
+#undef NO_FLUSH
+
+#ifdef VERBOSE
+static gint sincelast;
+#endif
+
+static gint
+alloc_scratch_image (GdkScratchImageInfo *image_info)
+{
+  if (image_info->static_image_idx == N_REGIONS)
+    {
+#ifndef NO_FLUSH
+      gdk_flush ();
+#endif
+#ifdef VERBOSE
+      g_print ("flush, %d puts since last flush\n", sincelast);
+      sincelast = 0;
+#endif
+      image_info->static_image_idx = 0;
+
+      /* Mark all regions that we might be filling in as completely
+       * full, to force new tiles to be allocated for subsequent
+       * images
+       */
+      image_info->horiz_y = GDK_SCRATCH_IMAGE_HEIGHT;
+      image_info->vert_x = GDK_SCRATCH_IMAGE_WIDTH;
+      image_info->tile_x = GDK_SCRATCH_IMAGE_WIDTH;
+      image_info->tile_y1 = image_info->tile_y2 = GDK_SCRATCH_IMAGE_HEIGHT;
+    }
+  return image_info->static_image_idx++;
+}
+
+/**
+ * _gdk_image_get_scratch:
+ * @width: desired width
+ * @height: desired height
+ * @depth: depth of image 
+ * @x: X location within returned image of scratch image
+ * @y: Y location within returned image of scratch image
+ * 
+ * Allocates an image of size width/height, up to a maximum
+ * of GDK_SCRATCH_IMAGE_WIDTHxGDK_SCRATCH_IMAGE_HEIGHT
+ * 
+ * Return value: a scratch image. This must be used by a
+ *  call to gdk_image_put() before any other calls to
+ *  _gdk_image_get_scratch()
+ **/
+GdkImage *
+_gdk_image_get_scratch (gint  width,
+                       gint  height,
+                       gint  depth,
+                       gint *x,
+                       gint *y)
+{
+  GdkScratchImageInfo *image_info;
+  GdkImage *image;
+  gint idx;
+
+  image_info = scratch_image_info_for_depth (depth);
+
+  if (width >= (GDK_SCRATCH_IMAGE_WIDTH >> 1))
+    {
+      if (height >= (GDK_SCRATCH_IMAGE_HEIGHT >> 1))
+       {
+         idx = alloc_scratch_image (image_info);
+         *x = 0;
+         *y = 0;
+       }
+      else
+       {
+         if (height + image_info->horiz_y > GDK_SCRATCH_IMAGE_HEIGHT)
+           {
+             image_info->horiz_idx = alloc_scratch_image (image_info);
+             image_info->horiz_y = 0;
+           }
+         idx = image_info->horiz_idx;
+         *x = 0;
+         *y = image_info->horiz_y;
+         image_info->horiz_y += height;
+       }
+    }
+  else
+    {
+      if (height >= (GDK_SCRATCH_IMAGE_HEIGHT >> 1))
+       {
+         if (width + image_info->vert_x > GDK_SCRATCH_IMAGE_WIDTH)
+           {
+             image_info->vert_idx = alloc_scratch_image (image_info);
+             image_info->vert_x = 0;
+           }
+         idx = image_info->vert_idx;
+         *x = image_info->vert_x;
+         *y = 0;
+         /* using 3 and -4 would be slightly more efficient on 32-bit machines
+            with > 1bpp displays */
+         image_info->vert_x += (width + 7) & -8;
+       }
+      else
+       {
+         if (width + image_info->tile_x > GDK_SCRATCH_IMAGE_WIDTH)
+           {
+             image_info->tile_y1 = image_info->tile_y2;
+             image_info->tile_x = 0;
+           }
+         if (height + image_info->tile_y1 > GDK_SCRATCH_IMAGE_HEIGHT)
+           {
+             image_info->tile_idx = alloc_scratch_image (image_info);
+             image_info->tile_x = 0;
+             image_info->tile_y1 = 0;
+             image_info->tile_y2 = 0;
+           }
+         if (height + image_info->tile_y1 > image_info->tile_y2)
+           image_info->tile_y2 = height + image_info->tile_y1;
+         idx = image_info->tile_idx;
+         *x = image_info->tile_x;
+         *y = image_info->tile_y1;
+         image_info->tile_x += (width + 7) & -8;
+       }
+    }
+  image = image_info->static_image[idx * image_info->n_images / N_REGIONS];
+  *x += GDK_SCRATCH_IMAGE_WIDTH * (idx % (N_REGIONS / image_info->n_images));
+#ifdef VERBOSE
+  g_print ("index %d, x %d, y %d (%d x %d)\n", idx, *x, *y, width, height);
+  sincelast++;
+#endif
+  return image;
+}
index aa557abd56aac34223810fd679572daa0f66fa56..327d56560d16d529c5313247f75928839dfb02ec 100644 (file)
@@ -158,6 +158,43 @@ void   _gdk_event_queue_append      (GdkEvent *event);
 
 void _gdk_event_button_generate (GdkEvent *event);
 
+#define GDK_SCRATCH_IMAGE_WIDTH 256
+#define GDK_SCRATCH_IMAGE_HEIGHT 64
+
+GdkImage* _gdk_image_new_for_depth (GdkImageType  type,
+                                   GdkVisual    *visual,
+                                   gint          width,
+                                   gint          height,
+                                   gint          depth);
+GdkImage *_gdk_image_get_scratch (gint  width,
+                                 gint  height,
+                                 gint  depth,
+                                 gint *x,
+                                 gint *y);
+
+/* Will most likely be exported in the future
+ */
+void _gdk_draw_pixbuf            (GdkDrawable  *drawable,
+                                 GdkGC        *gc,
+                                 GdkPixbuf    *pixbuf,
+                                 gint          src_x,
+                                 gint          src_y,
+                                 gint          dest_x,
+                                 gint          dest_y,
+                                 gint          width,
+                                 gint          height,
+                                 GdkRgbDither  dither,
+                                 gint          x_dither,
+                                 gint          y_dither);
+GdkImage *_gdk_drawable_copy_to_image (GdkDrawable  *drawable,
+                                      GdkImage     *image,
+                                      gint          src_x,
+                                      gint          src_y,
+                                      gint          dest_x,
+                                      gint          dest_y,
+                                      gint          width,
+                                      gint          height);
+
 /*************************************
  * Interfaces used by windowing code *
  *************************************/
@@ -204,6 +241,11 @@ GdkWindow* _gdk_windowing_window_get_pointer (GdkWindow       *window,
                                              gint            *y,
                                              GdkModifierType *mask);
 
+/* Return the number of bits-per-pixel for images of the specified depth.
+ * (Future: needs to be GdkDiplay specific.)
+ */
+gint _gdk_windowing_get_bits_for_depth (gint depth);
+
 #define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
 
 /* Called before processing updates for a window. This gives the windowing
index f4a99cab704be27178587643f0d7c0d04790845c..bfb0d941d1f246971d69649e740e065764545598 100644 (file)
@@ -72,7 +72,7 @@ bitmap1 (GdkImage    *image,
   int bpl;
   register guint8 data;
   guint8 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl, *orow = pixels;
 
   d (printf ("bitmap, no alpha\n"));
 
@@ -128,7 +128,7 @@ bitmap1a (GdkImage    *image,
   int bpl;
   register guint8 data;
   guint8 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl, *orow = pixels;
 
   d (printf ("bitmap, with alpha\n"));
 
@@ -183,7 +183,7 @@ rgb1 (GdkImage    *image,
   int bpl;
   register guint8 data;
   guint8 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl, *orow = pixels;
 
   d (printf ("1 bits/pixel\n"));
 
@@ -231,7 +231,7 @@ rgb1a (GdkImage    *image,
   int bpl;
   register guint8 data;
   guint8 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl, *orow = pixels;
   
   d (printf ("1 bits/pixel\n"));
 
@@ -279,7 +279,7 @@ rgb8 (GdkImage    *image,
   int bpl;
   guint32 mask;
   register guint32 data;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
   register guint8 *s;
   register guint8 *o;
 
@@ -326,7 +326,7 @@ rgb8a (GdkImage    *image,
   guint32 remap[256];
   register guint8 *s;  /* read 2 pixels at once */
   register guint32 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -387,7 +387,7 @@ rgb565lsb (GdkImage    *image,
   register guint8 *s;  /* read 2 pixels at once */
 #endif
   register guint16 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
   
   bpl = image->bpl;
   
@@ -490,7 +490,7 @@ rgb565msb (GdkImage    *image,
   register guint32 *s; /* read 2 pixels at once */
 #endif
   register guint16 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -596,7 +596,7 @@ rgb565alsb (GdkImage    *image,
 #endif
   register guint32 *o;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -659,7 +659,7 @@ rgb565amsb (GdkImage    *image,
 #endif
   register guint32 *o;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -717,7 +717,7 @@ rgb555lsb (GdkImage     *image,
   register guint8 *s;  /* read 2 pixels at once */
 #endif
   register guint16 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -821,7 +821,7 @@ rgb555msb (GdkImage    *image,
   register guint32 *s; /* read 2 pixels at once */
 #endif
   register guint16 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -922,7 +922,7 @@ rgb555alsb (GdkImage    *image,
 #endif
   register guint32 *o;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -985,7 +985,7 @@ rgb555amsb (GdkImage    *image,
 #endif
   register guint32 *o;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -1039,7 +1039,7 @@ rgb888alsb (GdkImage    *image,
 
   guint8 *s;   /* for byte order swapping */
   guint8 *o;
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 
   bpl = image->bpl;
 
@@ -1076,7 +1076,7 @@ rgb888lsb (GdkImage    *image,
   int xx, yy;
   int bpl;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
   guint8 *o, *s;
 
   bpl = image->bpl;
@@ -1112,7 +1112,7 @@ rgb888amsb (GdkImage    *image,
   int xx, yy;
   int bpl;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
 #ifdef LITTLE
   guint32 *o;
   guint32 *s;
@@ -1166,7 +1166,7 @@ rgb888msb (GdkImage    *image,
   int xx, yy;
   int bpl;
 
-  guint8 *srow = image->mem, *orow = pixels;
+  guint8 *srow = image->mem + y1 * image->bpl + x1 * image->bpp, *orow = pixels;
   guint8 *s;
   guint8 *o;
 
@@ -1207,8 +1207,7 @@ convert_real_slow (GdkImage    *image,
 {
   int xx, yy;
   int bpl;
-  guint8 *srow = image->mem, *orow = pixels;
-  guint8 *s;
+  guint8 *orow = pixels;
   guint8 *o;
   guint32 pixel;
   GdkVisual *v;
@@ -1225,7 +1224,6 @@ convert_real_slow (GdkImage    *image,
 
   for (yy = y1; yy < y2; yy++)
     {
-      s = srow;
       o = orow;
       for (xx = x1; xx < x2; xx++)
        {
@@ -1268,7 +1266,6 @@ convert_real_slow (GdkImage    *image,
          if (alpha)
            *o++ = 0xff;
        }
-      srow += bpl;
       orow += rowstride;
     }
 }
@@ -1481,6 +1478,7 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf   *dest,
   int src_width, src_height;
   GdkImage *image;
   int depth;
+  int x0, y0;
   
   /* General sanity checks */
 
@@ -1503,6 +1501,14 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf   *dest,
       g_return_val_if_fail (dest->bits_per_sample == 8, NULL);
     }
 
+  /* Create the pixbuf if needed */
+  if (!dest)
+    {
+      dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+      if (dest == NULL)
+        return NULL;
+    }
+
   if (cmap == NULL)
     cmap = gdk_drawable_get_colormap (src);
 
@@ -1536,19 +1542,28 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf   *dest,
       g_return_val_if_fail (dest_x + width <= dest->width, NULL);
       g_return_val_if_fail (dest_y + height <= dest->height, NULL);
     }
-  
-  /* Get Image in ZPixmap format (packed bits). */
-  image = gdk_image_get (src, src_x, src_y, width, height);
-  
-  if (image == NULL)
-    return NULL;
-  
-  dest = gdk_pixbuf_get_from_image (dest, image, cmap,
-                                    0, 0, dest_x, dest_y,
-                                    width, height);
-
-  gdk_image_destroy (image);
 
+  for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
+    {
+      gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
+      for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
+       {
+         gint xs0, ys0;
+         
+         gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
+         
+         image = _gdk_image_get_scratch (width1, height1, depth, &xs0, &ys0);
+
+         _gdk_drawable_copy_to_image (src, image,
+                                      src_x + x0, src_y + y0,
+                                      xs0, ys0, width1, height1);
+
+         gdk_pixbuf_get_from_image (dest, image, cmap,
+                                    xs0, ys0, dest_x + x0, dest_y + y0,
+                                    width1, height1);
+       }
+    }
+  
   return dest;
 }
         
@@ -1638,8 +1653,8 @@ gdk_pixbuf_get_from_image (GdkPixbuf   *dest,
              rowstride,
              alpha,
               src_x, src_y,
-              src_x + width,
-              src_y + height,
+              width,
+              height,
              cmap);
   
   return dest;
index 23c75121b4cd1bd2077b39f55c0ebc259cbc4db9..daaf6b31bb2cef9bc0f9f5db47e67ad621f1dcdf 100644 (file)
@@ -237,30 +237,19 @@ gdk_pixbuf_render_to_drawable (GdkPixbuf   *pixbuf,
  * @dest_y: Destination Y coordinate within drawable.
  * @width: Width of region to render, in pixels, or -1 to use pixbuf width.
  * @height: Height of region to render, in pixels, or -1 to use pixbuf height.
- * @alpha_mode: If the image does not have opacity information, this is ignored.
- * Otherwise, specifies how to handle transparency when rendering.
- * @alpha_threshold: If the image does have opacity information and @alpha_mode
- * is GDK_PIXBUF_ALPHA_BILEVEL, specifies the threshold value for opacity
- * values.
+ * @alpha_mode: Ignored. Present for backwards compatibility.
+ * @alpha_threshold: Ignored. Present for backwards compatibility
  * @dither: Dithering mode for GdkRGB.
  * @x_dither: X offset for dither.
  * @y_dither: Y offset for dither.
  *
- * Renders a rectangular portion of a pixbuf to a drawable.  This is done using
- * GdkRGB, so the specified drawable must have the GdkRGB visual and colormap.
+ * Renders a rectangular portion of a pixbuf to a drawable.  The destination
+ * drawable must have a colormap. All windows have a colormap, however, pixmaps
+ * only have colormap by default if they were created with a non-NULL window argument.
+ * Otherwise a colormap must be set on them with gdk_drawable_set_colormap.
  *
- * When used with #GDK_PIXBUF_ALPHA_BILEVEL, this function has to create a bitmap
- * out of the thresholded alpha channel of the image and, it has to set this
- * bitmap as the clipping mask for the GC used for drawing.  This can be a
- * significant performance penalty depending on the size and the complexity of
- * the alpha channel of the image.  If performance is crucial, consider handling
- * the alpha channel yourself (possibly by caching it in your application) and
- * using gdk_pixbuf_render_to_drawable() or GdkRGB directly instead.
- *
- * The #GDK_PIXBUF_ALPHA_FULL mode involves round trips to the X
- * server, and may also be somewhat slow in its current implementation
- * (though in the future it could be made significantly faster, in
- * principle).
+ * On older X servers, rendering pixbufs with an alpha channel involves round trips
+ * to the X server, and may be somewhat slow.
  **/
 void
 gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf   *pixbuf,
@@ -273,165 +262,9 @@ gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf   *pixbuf,
                                     GdkRgbDither       dither,
                                     int x_dither, int y_dither)
 {
-  GdkBitmap *bitmap = NULL;
-  GdkGC *gc;
-  GdkPixbuf *composited = NULL;
-  gint dwidth, dheight;
-  GdkRegion *clip;
-  GdkRegion *drect;
-  GdkRectangle tmp_rect;
-  
-  g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
-  g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
-  g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
-  g_return_if_fail (pixbuf->bits_per_sample == 8);
-
-  g_return_if_fail (drawable != NULL);
-
-  if (width == -1) 
-    width = pixbuf->width;
-  if (height == -1)
-    height = pixbuf->height;
-
-  g_return_if_fail (width >= 0 && height >= 0);
-  g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
-  g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
-
-  /* Clip to the drawable; this is required for get_from_drawable() so
-   * can't be done implicitly
-   */
-  
-  if (dest_x < 0)
-    {
-      src_x -= dest_x;
-      width += dest_x;
-      dest_x = 0;
-    }
-
-  if (dest_y < 0)
-    {
-      src_y -= dest_y;
-      height += dest_y;
-      dest_y = 0;
-    }
-
-  gdk_drawable_get_size (drawable, &dwidth, &dheight);
-
-  if ((dest_x + width) > dwidth)
-    width = dwidth - dest_x;
-
-  if ((dest_y + height) > dheight)
-    height = dheight - dest_y;
-
-  if (width <= 0 || height <= 0)
-    return;
-
-  /* Clip to the clip region; this avoids getting more
-   * image data from the server than we need to.
-   */
-  
-  tmp_rect.x = dest_x;
-  tmp_rect.y = dest_y;
-  tmp_rect.width = width;
-  tmp_rect.height = height;
-
-  drect = gdk_region_rectangle (&tmp_rect);
-  clip = gdk_drawable_get_clip_region (drawable);
-
-  gdk_region_intersect (drect, clip);
-
-  gdk_region_get_clipbox (drect, &tmp_rect);
-  
-  gdk_region_destroy (drect);
-  gdk_region_destroy (clip);
-
-  if (tmp_rect.width == 0 ||
-      tmp_rect.height == 0)
-    return;
-  
-  /* Actually draw */
-  
-  gc = gdk_gc_new (drawable);
-
-  if (pixbuf->has_alpha)
-    {
-      if (alpha_mode == GDK_PIXBUF_ALPHA_FULL)
-        {
-          GdkPixbuf *sub = NULL;
-          
-          composited = gdk_pixbuf_get_from_drawable (NULL,
-                                                     drawable,
-                                                     NULL,
-                                                     dest_x, dest_y,
-                                                     0, 0,
-                                                     width, height);
-
-          if (composited)
-            {
-              if (src_x != 0 || src_y != 0)
-                {
-                  sub = gdk_pixbuf_new_subpixbuf (pixbuf, src_x, src_y,
-                                                  width, height);
-                }
-              
-              gdk_pixbuf_composite (sub ? sub : pixbuf,
-                                    composited,
-                                    0, 0,
-                                    width, height,
-                                    0, 0,
-                                    1.0, 1.0,
-                                    GDK_INTERP_BILINEAR,
-                                    255);
-              
-              if (sub)
-                g_object_unref (G_OBJECT (sub));
-            }
-          else
-            alpha_mode = GDK_PIXBUF_ALPHA_BILEVEL; /* fall back */
-        }
-
-      if (alpha_mode == GDK_PIXBUF_ALPHA_BILEVEL)
-        {
-          bitmap = gdk_pixmap_new (NULL, width, height, 1);
-          gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap,
-                                             src_x, src_y,
-                                             0, 0,
-                                             width, height,
-                                             alpha_threshold);
-          
-          gdk_gc_set_clip_mask (gc, bitmap);
-          gdk_gc_set_clip_origin (gc, dest_x, dest_y);
-        }
-    }
-
-  if (composited)
-    {
-      gdk_pixbuf_render_to_drawable (composited,
-                                     drawable, gc,
-                                     0, 0,
-                                     dest_x, dest_y,
-                                     width, height,
-                                     dither,
-                                     x_dither, y_dither);
-    }
-  else
-    {
-      gdk_pixbuf_render_to_drawable (pixbuf,
-                                     drawable, gc,
-                                     src_x, src_y,
-                                     dest_x, dest_y,
-                                     width, height,
-                                     dither,
-                                     x_dither, y_dither);
-    }
-
-  if (bitmap)
-    gdk_bitmap_unref (bitmap);
-
-  if (composited)
-    g_object_unref (G_OBJECT (composited));
-
-  gdk_gc_unref (gc);
+  _gdk_draw_pixbuf (drawable, NULL, pixbuf,
+                   src_x, src_y, dest_x, dest_y, width, height,
+                   dither, x_dither, y_dither);
 }
 
 /**
@@ -531,5 +364,3 @@ gdk_pixbuf_render_pixmap_and_mask_for_colormap (GdkPixbuf   *pixbuf,
        *mask_return = NULL;
     }
 }
-
-
index 088e181a5ec8262fcdc80d1452eecb731bdd7316..5e757246fb2db886616a388f94b689e55d1ca0c9 100644 (file)
@@ -102,16 +102,32 @@ static void   gdk_pixmap_draw_image     (GdkDrawable     *drawable,
                                          gint             ydest,
                                          gint             width,
                                          gint             height);
+static void   gdk_pixmap_draw_pixbuf    (GdkDrawable     *drawable,
+                                        GdkGC           *gc,
+                                        GdkPixbuf       *pixbuf,
+                                        gint             src_x,
+                                        gint             src_y,
+                                        gint             dest_x,
+                                        gint             dest_y,
+                                        gint             width,
+                                        gint             height,
+                                        GdkRgbDither     dither,
+                                        gint             x_dither,
+                                        gint             y_dither);
+
 
 static void   gdk_pixmap_real_get_size  (GdkDrawable     *drawable,
                                          gint            *width,
                                          gint            *height);
 
-static GdkImage* gdk_pixmap_get_image (GdkDrawable *drawable,
-                                      gint         x,
-                                      gint         y,
-                                      gint         width,
-                                      gint         height);
+static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable,
+                                          GdkImage    *image,
+                                          gint         src_x,
+                                          gint         src_y,
+                                          gint         dest_x,
+                                          gint         dest_y,
+                                          gint         width,
+                                          gint         height);
 
 static GdkVisual*   gdk_pixmap_real_get_visual   (GdkDrawable *drawable);
 static gint         gdk_pixmap_real_get_depth    (GdkDrawable *drawable);
@@ -182,12 +198,13 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass)
   drawable_class->draw_lines = gdk_pixmap_draw_lines;
   drawable_class->draw_glyphs = gdk_pixmap_draw_glyphs;
   drawable_class->draw_image = gdk_pixmap_draw_image;
+  drawable_class->_draw_pixbuf = gdk_pixmap_draw_pixbuf;
   drawable_class->get_depth = gdk_pixmap_real_get_depth;
   drawable_class->get_size = gdk_pixmap_real_get_size;
   drawable_class->set_colormap = gdk_pixmap_real_set_colormap;
   drawable_class->get_colormap = gdk_pixmap_real_get_colormap;
   drawable_class->get_visual = gdk_pixmap_real_get_visual;
-  drawable_class->get_image = gdk_pixmap_get_image;
+  drawable_class->_copy_to_image = gdk_pixmap_copy_to_image;
 }
 
 static void
@@ -366,6 +383,27 @@ gdk_pixmap_draw_image (GdkDrawable     *drawable,
                   width, height);
 }
 
+static void
+gdk_pixmap_draw_pixbuf (GdkDrawable     *drawable,
+                       GdkGC           *gc,
+                       GdkPixbuf       *pixbuf,
+                       gint             src_x,
+                       gint             src_y,
+                       gint             dest_x,
+                       gint             dest_y,
+                       gint             width,
+                       gint             height,
+                       GdkRgbDither     dither,
+                       gint             x_dither,
+                       gint             y_dither)
+{
+  GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+
+  _gdk_draw_pixbuf (private->impl, gc, pixbuf,
+                   src_x, src_y, dest_x, dest_y, width, height,
+                   dither, x_dither, y_dither);
+}
+
 static void
 gdk_pixmap_real_get_size (GdkDrawable *drawable,
                           gint *width,
@@ -418,16 +456,21 @@ gdk_pixmap_real_get_colormap (GdkDrawable *drawable)
 }
 
 static GdkImage*
-gdk_pixmap_get_image (GdkDrawable     *drawable,
-                      gint             x,
-                      gint             y,
-                      gint             width,
-                      gint             height)
+gdk_pixmap_copy_to_image (GdkDrawable     *drawable,
+                         GdkImage        *image,
+                         gint             src_x,
+                         gint             src_y,
+                         gint             dest_x,
+                         gint             dest_y,
+                         gint             width,
+                         gint             height)
 {
   g_return_val_if_fail (GDK_IS_PIXMAP (drawable), NULL);
   
-  return gdk_drawable_get_image (((GdkPixmapObject*)drawable)->impl,
-                                 x, y, width, height);
+  return _gdk_drawable_copy_to_image (((GdkPixmapObject*)drawable)->impl,
+                                     image,
+                                     src_x, src_y, dest_x, dest_y,
+                                     width, height);
 }
 
 static GdkBitmap *
index d7ce391cd2950e1f4a841a3d8df542fc1f9cd1e9..042d4ca339f631ac00d81e45f7f39c8e12a5e222 100644 (file)
 
 #define ENABLE_GRAYSCALE
 
-#ifdef GDK_RGB_STANDALONE
-
-/* Compiling as a standalone module (i.e. with Gtk 1.0) */
-/* gtk/gtk.h is already included in gdkrgbstub.c */
-#include "config.h"
-#include <gdk/gdkprivate.h>
-
-#else
-
-/* Compiling as a part of Gtk 1.1 or later */
 #include "config.h"
 #include "gdkprivate.h"
+#include "gdkinternals.h"      /* _gdk_windowing_get_bits_for_depth() */
 
-#endif
-
-#include "gdk.h"               /* For gdk_flush() */
 #include "gdkrgb.h"
 
 typedef struct _GdkRgbInfo     GdkRgbInfo;
@@ -84,30 +72,10 @@ static const gchar* visual_names[] =
   "direct color",
 };
 
-#define REGION_WIDTH 256
-#define STAGE_ROWSTRIDE (REGION_WIDTH * 3)
-#define REGION_HEIGHT 64
+#define STAGE_ROWSTRIDE (GDK_SCRATCH_IMAGE_WIDTH * 3)
 
-/* We have N_REGION REGION_WIDTH x REGION_HEIGHT regions divided
- * up between n_images different images. possible_n_images gives
- * various divisors of N_REGIONS. The reason for allowing this
- * flexibility is that we want to create as few images as possible,
- * but we want to deal with the abberant systems that have a SHMMAX
- * limit less than
- *
- * REGION_WIDTH * REGION_HEIGHT * N_REGIONS * 4 (384k)
- *
- * (Are there any such?)
+/* Some of these fields should go, as they're not being used at all. (?)
  */
-#define N_REGIONS 6
-static const int possible_n_images[] = { 1, 2, 3, 6 };
-
-/* Some of these fields should go, as they're not being used at all.
-   Globals should generally migrate into here - it's very likely that
-   we'll want to run more than one GdkRgbInfo context at the same time
-   (i.e. some but not all windows have privately installed
-   colormaps). */
-
 struct _GdkRgbInfo
 {
   GdkVisual *visual;
@@ -147,32 +115,6 @@ struct _GdkRgbInfo
   GdkRgbConvFunc conv_indexed;
   GdkRgbConvFunc conv_indexed_d;
 
-  gint n_images;
-  GdkImage *static_image[N_REGIONS];
-  gint static_image_idx;
-
-  /* In order to optimize filling fractions, we simultaneously fill in up
-   * to three regions of size REGION_WIDTH * REGION_HEIGHT: one
-   * for images that are taller than REGION_HEIGHT / 2, and must
-   * be tiled horizontally. One for images that are wider than
-   * REGION_WIDTH / 2 and must be tiled vertically, and a third
-   * for images smaller than REGION_HEIGHT / 2 x REGION_WIDTH x 2
-   * that we tile in horizontal rows.
-   */
-  gint horiz_idx;
-  gint horiz_y;
-  gint vert_idx;
-  gint vert_x;
-  
-  /* tile_y1 and tile_y2 define the horizontal band into
-   * which we are tiling images. tile_x is the x extent to
-   * which that is filled
-   */
-  gint tile_idx;
-  gint tile_x;
-  gint tile_y1;
-  gint tile_y2;
-
   guchar *colorcube;
   guchar *colorcube_d;
 
@@ -562,7 +504,7 @@ gdk_rgb_choose_visual (void)
   return best_visual;
 }
 
-static void gdk_rgb_select_conv (GdkRgbInfo *image_info, GdkImage *image);
+static void gdk_rgb_select_conv (GdkRgbInfo *image_info);
 
 static void
 gdk_rgb_set_gray_cmap (GdkRgbInfo  *image_info,
@@ -606,39 +548,10 @@ gdk_rgb_set_gray_cmap (GdkRgbInfo  *image_info,
     }
 }
 
-static gboolean
-gdk_rgb_allocate_images (GdkRgbInfo *image_info,
-                        gint        n_images,
-                        gboolean    shared)
-{
-  gint i;
-  
-  for (i = 0; i < n_images; i++)
-    {
-      image_info->static_image[i] = gdk_image_new (shared ? GDK_IMAGE_SHARED : GDK_IMAGE_NORMAL,
-                                                  image_info->visual,
-                                                  REGION_WIDTH * (N_REGIONS / n_images), REGION_HEIGHT);
-
-      if (!image_info->static_image[i])
-       {
-         gint j;
-
-         for (j = 0; j < i; j++)
-           gdk_image_unref (image_info->static_image[i]);
-
-         return FALSE;
-       }
-    }
-  
-  return TRUE;
-}
-
 static void
 gdk_rgb_free_info (GdkRgbInfo *image_info)
 {
-  gint i;
   GSList *tmp_list;
-
   
   if (image_info->stage_buf)
     g_free (image_info->stage_buf);
@@ -649,9 +562,6 @@ gdk_rgb_free_info (GdkRgbInfo *image_info)
   if (image_info->own_gc)
     gdk_gc_unref (image_info->own_gc);
 
-  for (i = 0; i < image_info->n_images; i++)
-    gdk_image_unref (image_info->static_image[i]);
-
   if (image_info->colorcube)
     g_free (image_info->colorcube);
   
@@ -679,7 +589,6 @@ static GdkRgbInfo *
 gdk_rgb_create_info (GdkVisual *visual, GdkColormap *colormap)
 {
   GdkRgbInfo *image_info;
-  gint i;
 
   image_info = g_new0 (GdkRgbInfo, 1);
 
@@ -765,33 +674,9 @@ gdk_rgb_create_info (GdkVisual *visual, GdkColormap *colormap)
 
   image_info->bitmap = (image_info->visual->depth == 1);
 
-  /* Try to allocate as few possible shared images */
-  for (i=0; i < G_N_ELEMENTS (possible_n_images); i++)
-    {
-      if (gdk_rgb_allocate_images (image_info, possible_n_images[i], TRUE))
-       {
-         image_info->n_images = possible_n_images[i];
-         break;
-       }
-    }
-
-  /* If that fails, just allocate N_REGIONS normal images */
-  if (i == G_N_ELEMENTS (possible_n_images))
-    {
-      gdk_rgb_allocate_images (image_info, N_REGIONS, FALSE);
-      image_info->n_images = N_REGIONS;
-    }
+  image_info->bpp = (_gdk_windowing_get_bits_for_depth (image_info->visual->depth) + 7) / 8;
 
-  image_info->bpp = image_info->static_image[0]->bpp;
-
-  image_info->static_image_idx = 0;
-
-  image_info->horiz_y = REGION_HEIGHT;
-  image_info->vert_x = REGION_WIDTH;
-  image_info->tile_x = REGION_WIDTH;
-  image_info->tile_y1 = image_info->tile_y2 = REGION_HEIGHT;
-
-  gdk_rgb_select_conv (image_info, image_info->static_image[0]);
+  gdk_rgb_select_conv (image_info);
 
   if (!gdk_rgb_quark)
     gdk_rgb_quark = g_quark_from_static_string (gdk_rgb_key);
@@ -1415,7 +1300,7 @@ gdk_rgb_convert_gray8_gray (GdkRgbInfo *image_info, GdkImage *image,
 #ifdef HAIRY_CONVERT_565
 /* Render a 24-bit RGB image in buf into the GdkImage, without dithering.
    This assumes native byte ordering - what should really be done is to
-   check whether static_image->byte_order is consistent with the _ENDIAN
+   check whether the the image byte_order is consistent with the _ENDIAN
    config flag, and if not, use a different function.
 
    This one is even faster than the one below - its inner loop loads 3
@@ -1499,7 +1384,7 @@ gdk_rgb_convert_565 (GdkRgbInfo *image_info, GdkImage *image,
 #else
 /* Render a 24-bit RGB image in buf into the GdkImage, without dithering.
    This assumes native byte ordering - what should really be done is to
-   check whether static_image->byte_order is consistent with the _ENDIAN
+   check whether the image byte_order is consistent with the _ENDIAN
    config flag, and if not, use a different function.
 
    This routine is faster than the one included with Gtk 1.0 for a number
@@ -2670,7 +2555,7 @@ static guchar *
 gdk_rgb_ensure_stage (GdkRgbInfo *image_info)
 {
   if (image_info->stage_buf == NULL)
-    image_info->stage_buf = g_malloc (REGION_HEIGHT * STAGE_ROWSTRIDE);
+    image_info->stage_buf = g_malloc (GDK_SCRATCH_IMAGE_HEIGHT * STAGE_ROWSTRIDE);
   return image_info->stage_buf;
 }
 
@@ -2873,7 +2758,7 @@ gdk_rgb_convert_indexed_generic_d (GdkRgbInfo *image_info, GdkImage *image,
 /* Select a conversion function based on the visual and a
    representative image. */
 static void
-gdk_rgb_select_conv (GdkRgbInfo *image_info, GdkImage *image)
+gdk_rgb_select_conv (GdkRgbInfo *image_info)
 {
   GdkByteOrder byte_order;
   gint depth, bpp, byterev;
@@ -2887,9 +2772,9 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info, GdkImage *image)
 
   depth = image_info->visual->depth;
 
-  bpp = image->bits_per_pixel;
+  bpp = _gdk_windowing_get_bits_for_depth (image_info->visual->depth);
 
-  byte_order = image->byte_order;
+  byte_order = image_info->visual->byte_order;
   if (gdk_rgb_verbose)
     g_print ("Chose visual type=%s depth=%d, image bpp=%d, %s first\n",
             visual_names[image_info->visual->type], image_info->visual->depth,
@@ -3066,116 +2951,6 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info, GdkImage *image)
   image_info->conv_indexed_d = conv_indexed_d;
 }
 
-#ifdef VERBOSE
-static gint sincelast;
-#endif
-
-/* Defining NO_FLUSH can cause inconsistent screen updates, but is useful
-   for performance evaluation. */
-
-#undef NO_FLUSH
-
-static gint
-gdk_rgb_alloc_scratch_image (GdkRgbInfo *image_info)
-{
-  if (image_info->static_image_idx == N_REGIONS)
-    {
-#ifndef NO_FLUSH
-      gdk_flush ();
-#endif
-#ifdef VERBOSE
-      g_print ("flush, %d puts since last flush\n", sincelast);
-      sincelast = 0;
-#endif
-      image_info->static_image_idx = 0;
-
-      /* Mark all regions that we might be filling in as completely
-       * full, to force new tiles to be allocated for subsequent
-       * images
-       */
-      image_info->horiz_y = REGION_HEIGHT;
-      image_info->vert_x = REGION_WIDTH;
-      image_info->tile_x = REGION_WIDTH;
-      image_info->tile_y1 = image_info->tile_y2 = REGION_HEIGHT;
-    }
-  return image_info->static_image_idx++;
-}
-
-static GdkImage *
-gdk_rgb_alloc_scratch (GdkRgbInfo *image_info,
-                      gint width, gint height, gint *x0, gint *y0)
-{
-  GdkImage *image;
-  gint idx;
-
-  if (width >= (REGION_WIDTH >> 1))
-    {
-      if (height >= (REGION_HEIGHT >> 1))
-       {
-         idx = gdk_rgb_alloc_scratch_image (image_info);
-         *x0 = 0;
-         *y0 = 0;
-       }
-      else
-       {
-         if (height + image_info->horiz_y > REGION_HEIGHT)
-           {
-             image_info->horiz_idx = gdk_rgb_alloc_scratch_image (image_info);
-             image_info->horiz_y = 0;
-           }
-         idx = image_info->horiz_idx;
-         *x0 = 0;
-         *y0 = image_info->horiz_y;
-         image_info->horiz_y += height;
-       }
-    }
-  else
-    {
-      if (height >= (REGION_HEIGHT >> 1))
-       {
-         if (width + image_info->vert_x > REGION_WIDTH)
-           {
-             image_info->vert_idx = gdk_rgb_alloc_scratch_image (image_info);
-             image_info->vert_x = 0;
-           }
-         idx = image_info->vert_idx;
-         *x0 = image_info->vert_x;
-         *y0 = 0;
-         /* using 3 and -4 would be slightly more efficient on 32-bit machines
-            with > 1bpp displays */
-         image_info->vert_x += (width + 7) & -8;
-       }
-      else
-       {
-         if (width + image_info->tile_x > REGION_WIDTH)
-           {
-             image_info->tile_y1 = image_info->tile_y2;
-             image_info->tile_x = 0;
-           }
-         if (height + image_info->tile_y1 > REGION_HEIGHT)
-           {
-             image_info->tile_idx = gdk_rgb_alloc_scratch_image (image_info);
-             image_info->tile_x = 0;
-             image_info->tile_y1 = 0;
-             image_info->tile_y2 = 0;
-           }
-         if (height + image_info->tile_y1 > image_info->tile_y2)
-           image_info->tile_y2 = height + image_info->tile_y1;
-         idx = image_info->tile_idx;
-         *x0 = image_info->tile_x;
-         *y0 = image_info->tile_y1;
-         image_info->tile_x += (width + 7) & -8;
-       }
-    }
-  image = image_info->static_image[idx * image_info->n_images / N_REGIONS];
-  *x0 += REGION_WIDTH * (idx % (N_REGIONS / image_info->n_images));
-#ifdef VERBOSE
-  g_print ("index %d, x %d, y %d (%d x %d)\n", idx, *x0, *y0, width, height);
-  sincelast++;
-#endif
-  return image;
-}
-
 static void
 gdk_draw_rgb_image_core (GdkRgbInfo *image_info,
                         GdkDrawable *drawable,
@@ -3212,15 +2987,15 @@ gdk_draw_rgb_image_core (GdkRgbInfo *image_info,
        }
       gc = image_info->own_gc;
     }
-  for (y0 = 0; y0 < height; y0 += REGION_HEIGHT)
+  for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
     {
-      height1 = MIN (height - y0, REGION_HEIGHT);
-      for (x0 = 0; x0 < width; x0 += REGION_WIDTH)
+      height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
+      for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
        {
-         width1 = MIN (width - x0, REGION_WIDTH);
+         width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
          buf_ptr = buf + y0 * rowstride + x0 * pixstride;
 
-         image = gdk_rgb_alloc_scratch (image_info, width1, height1, &xs0, &ys0);
+         image = _gdk_image_get_scratch (width1, height1, image_info->visual->depth, &xs0, &ys0);
 
          conv (image_info, image, xs0, ys0, width1, height1, buf_ptr, rowstride,
                x + x0 + xdith, y + y0 + ydith, cmap);
index 28c2b26fefa32019120babb1864c7e807ea2db65..ea9fdc2b2324cbd12e8ab28f2f534c8508ff6e84 100644 (file)
@@ -126,12 +126,27 @@ static void   gdk_window_draw_image     (GdkDrawable     *drawable,
                                          gint             width,
                                          gint             height);
 
-static GdkImage*  gdk_window_get_image  (GdkDrawable     *drawable,
-                                         gint             x,
-                                         gint             y,
-                                         gint             width,
-                                         gint             height);
-
+static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
+                                   GdkGC           *gc,
+                                   GdkPixbuf       *pixbuf,
+                                   gint             src_x,
+                                   gint             src_y,
+                                   gint             dest_x,
+                                   gint             dest_y,
+                                   gint             width,
+                                   gint             height,
+                                   GdkRgbDither     dither,
+                                   gint             x_dither,
+                                   gint             y_dither);
+
+static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
+                                          GdkImage    *image,
+                                          gint         src_x,
+                                          gint         src_y,
+                                          gint         dest_x,
+                                          gint         dest_y,
+                                          gint         width,
+                                          gint         height);
 
 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
                                          gint            *width,
@@ -223,12 +238,13 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   drawable_class->draw_lines = gdk_window_draw_lines;
   drawable_class->draw_glyphs = gdk_window_draw_glyphs;
   drawable_class->draw_image = gdk_window_draw_image;
+  drawable_class->_draw_pixbuf = gdk_window_draw_pixbuf;
   drawable_class->get_depth = gdk_window_real_get_depth;
   drawable_class->get_size = gdk_window_real_get_size;
   drawable_class->set_colormap = gdk_window_real_set_colormap;
   drawable_class->get_colormap = gdk_window_real_get_colormap;
   drawable_class->get_visual = gdk_window_real_get_visual;
-  drawable_class->get_image = gdk_window_get_image;
+  drawable_class->_copy_to_image = gdk_window_copy_to_image;
   drawable_class->get_clip_region = gdk_window_get_clip_region;
   drawable_class->get_visible_region = gdk_window_get_visible_region;
   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
@@ -1862,6 +1878,65 @@ gdk_window_draw_image (GdkDrawable *drawable,
   RESTORE_GC (gc);
 }
 
+static void
+gdk_window_draw_pixbuf (GdkDrawable     *drawable,
+                       GdkGC           *gc,
+                       GdkPixbuf       *pixbuf,
+                       gint             src_x,
+                       gint             src_y,
+                       gint             dest_x,
+                       gint             dest_y,
+                       gint             width,
+                       gint             height,
+                       GdkRgbDither     dither,
+                       gint             x_dither,
+                       gint             y_dither)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+  
+  if (gc)
+    {
+      OFFSET_GC (gc);
+  
+      if (private->paint_stack)
+       {
+         GdkWindowPaint *paint = private->paint_stack->data;
+         _gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
+                           dest_x - x_offset, dest_y - y_offset,
+                           width, height,
+                           dither, x_dither - x_offset, y_dither - y_offset);
+       }
+      else
+       _gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+                         dest_x - x_offset, dest_y - y_offset,
+                         width, height,
+                         dither, x_dither, y_dither);
+      
+      RESTORE_GC (gc);
+    }
+  else
+    {
+      gint x_offset, y_offset;
+      gdk_window_get_offsets (drawable, &x_offset, &y_offset);
+      
+      if (private->paint_stack)
+       {
+         GdkWindowPaint *paint = private->paint_stack->data;
+         _gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
+                           dest_x - x_offset, dest_y - y_offset,
+                           width, height,
+                           dither, x_dither - x_offset, y_dither - y_offset);
+       }
+      else
+       _gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+                         dest_x - x_offset, dest_y - y_offset,
+                         width, height,
+                         dither, x_dither, y_dither);
+    }
+}
 
 static void
 gdk_window_real_get_size (GdkDrawable *drawable,
@@ -1927,11 +2002,14 @@ gdk_window_real_get_colormap (GdkDrawable *drawable)
 }
                       
 static GdkImage*
-gdk_window_get_image (GdkDrawable *drawable,
-                      gint         x,
-                      gint         y,
-                      gint         width,
-                      gint         height)
+gdk_window_copy_to_image (GdkDrawable     *drawable,
+                         GdkImage        *image,
+                         gint             src_x,
+                         gint             src_y,
+                         gint             dest_x,
+                         gint             dest_y,
+                         gint             width,
+                         gint             height)
 {
   gint x_offset, y_offset;
   
@@ -1946,10 +2024,12 @@ gdk_window_get_image (GdkDrawable *drawable,
   
   _gdk_windowing_window_get_offsets (drawable, &x_offset, &y_offset);
   
-  return gdk_drawable_get_image (((GdkWindowObject*)drawable)->impl,
-                                 x - x_offset,
-                                 y - y_offset,
-                                 width, height);
+  return _gdk_drawable_copy_to_image (((GdkWindowObject*)drawable)->impl,
+                                     image,
+                                     src_x - x_offset,
+                                     src_y - y_offset,
+                                     dest_x, dest_y,
+                                     width, height);
 }
 
 /* Code for dirty-region queueing
index 0ca8d12201225ccb0ea45ffc2a027f4c06820034..96f6b05f8ae30def6610383af941ddc490e89115 100644 (file)
@@ -35,6 +35,7 @@
 #endif
 
 #include <stdlib.h>
+#include <string.h>            /* for memcpy() */
 
 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
 #define USE_SHM
@@ -119,6 +120,20 @@ static void gdk_x11_draw_image     (GdkDrawable     *drawable,
                                     gint             ydest,
                                     gint             width,
                                     gint             height);
+#ifdef HAVE_XFT
+static void gdk_x11_draw_pixbuf    (GdkDrawable     *drawable,
+                                   GdkGC           *gc,
+                                   GdkPixbuf       *pixbuf,
+                                   gint             src_x,
+                                   gint             src_y,
+                                   gint             dest_x,
+                                   gint             dest_y,
+                                   gint             width,
+                                   gint             height,
+                                   GdkRgbDither     dither,
+                                   gint             x_dither,
+                                   gint             y_dither);
+#endif /* HAVE_XFT */
 
 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
                                     GdkColormap    *colormap);
@@ -185,6 +200,9 @@ gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
   drawable_class->draw_lines = gdk_x11_draw_lines;
   drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
   drawable_class->draw_image = gdk_x11_draw_image;
+#ifdef HAVE_XFT  
+  drawable_class->_draw_pixbuf = gdk_x11_draw_pixbuf;
+#endif /* HAVE_XFT */
   
   drawable_class->set_colormap = gdk_x11_set_colormap;
   drawable_class->get_colormap = gdk_x11_get_colormap;
@@ -192,7 +210,7 @@ gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
   drawable_class->get_depth = gdk_x11_get_depth;
   drawable_class->get_visual = gdk_x11_get_visual;
   
-  drawable_class->get_image = _gdk_x11_get_image;
+  drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
 }
 
 static void
@@ -204,6 +222,17 @@ gdk_drawable_impl_x11_finalize (GObject *object)
 }
 
 #ifdef HAVE_XFT
+gboolean
+_gdk_x11_have_render (void)
+{
+  /* This check is cheap, but if we have to do version checks, we will
+   * need to cache the result since version checks are round-trip
+   */
+  int event_base, error_base;
+
+  return XRenderQueryExtension (gdk_display, &event_base, &error_base);
+}
+
 static Picture
 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
 {
@@ -225,7 +254,8 @@ gdk_x11_drawable_get_picture (GdkDrawable *drawable)
        }
 
       format = XRenderFindVisualFormat (impl->xdisplay, GDK_VISUAL_XVISUAL (visual));
-      impl->picture = XRenderCreatePicture (impl->xdisplay, impl->xid, format, 0, NULL);
+      if (format)
+       impl->picture = XRenderCreatePicture (impl->xdisplay, impl->xid, format, 0, NULL);
     }
 
   return impl->picture;
@@ -752,3 +782,536 @@ gdk_x11_drawable_get_xid (GdkDrawable *drawable)
 
   return ((GdkDrawableImplX11 *)impl)->xid;
 }
+
+/* Code for accelerated alpha compositing using the RENDER extension.
+ * It's a bit long because there are lots of possibilities for
+ * what's the fastest depending on the available picture formats,
+ * whether we can used shared pixmaps, etc.
+ */
+#ifdef HAVE_XFT
+typedef enum {
+  FORMAT_NONE,
+  FORMAT_EXACT_MASK,
+  FORMAT_ARGB_MASK,
+  FORMAT_ARGB
+} FormatType;
+
+static FormatType
+select_format (Display            *xdisplay,
+              XRenderPictFormat **format,
+              XRenderPictFormat **mask)
+{
+  XRenderPictFormat pf;
+  
+
+/* Look for a 32-bit xRGB and Axxx formats that exactly match the
+ * in memory data format. We can use them as pixmap and mask
+ * to deal with non-premultiplied data.
+ */
+
+  pf.type = PictTypeDirect;
+  pf.depth = 32;
+  pf.direct.redMask = 0xff;
+  pf.direct.greenMask = 0xff;
+  pf.direct.blueMask = 0xff;
+  
+  pf.direct.alphaMask = 0;
+  if (ImageByteOrder (xdisplay) == LSBFirst)
+    {
+      /* ABGR */
+      pf.direct.red = 0;
+      pf.direct.green = 8;
+      pf.direct.blue = 16;
+    }
+  else
+    {
+      /* RGBA */
+      pf.direct.red = 24;
+      pf.direct.green = 16;
+      pf.direct.blue = 8;
+    }
+  
+  *format = XRenderFindFormat (xdisplay,
+                              (PictFormatType | PictFormatDepth |
+                               PictFormatRedMask | PictFormatRed |
+                               PictFormatGreenMask | PictFormatGreen |
+                               PictFormatBlueMask | PictFormatBlue |
+                               PictFormatAlphaMask),
+                              &pf,
+                              0);
+
+  pf.direct.alphaMask = 0xff;
+  if (ImageByteOrder (xdisplay) == LSBFirst)
+    {
+      /* ABGR */
+      pf.direct.alpha = 24;
+    }
+  else
+    {
+      pf.direct.alpha = 0;
+    }
+  
+  *mask = XRenderFindFormat (xdisplay,
+                            (PictFormatType | PictFormatDepth |
+                             PictFormatAlphaMask | PictFormatAlpha),
+                            &pf,
+                            0);
+
+  if (*format && *mask)
+    return FORMAT_EXACT_MASK;
+
+  /* OK, that failed, now look for xRGB and Axxx formats in
+   * RENDER's preferred order
+   */
+  pf.direct.alphaMask = 0;
+  /* ARGB */
+  pf.direct.red = 16;
+  pf.direct.green = 8;
+  pf.direct.blue = 0;
+  
+  *format = XRenderFindFormat (xdisplay,
+                              (PictFormatType | PictFormatDepth |
+                               PictFormatRedMask | PictFormatRed |
+                               PictFormatGreenMask | PictFormatGreen |
+                               PictFormatBlueMask | PictFormatBlue |
+                               PictFormatAlphaMask),
+                              &pf,
+                              0);
+
+  pf.direct.alphaMask = 0xff;
+  pf.direct.alpha = 24;
+  
+  *mask = XRenderFindFormat (xdisplay,
+                            (PictFormatType | PictFormatDepth |
+                             PictFormatAlphaMask | PictFormatAlpha),
+                            &pf,
+                            0);
+
+  if (*format && *mask)
+    return FORMAT_ARGB_MASK;
+
+  /* Finally, if neither of the above worked, fall back to
+   * looking for combined ARGB -- we'll premultiply ourselves.
+   */
+
+  pf.type = PictTypeDirect;
+  pf.depth = 32;
+  pf.direct.red = 16;
+  pf.direct.green = 8;
+  pf.direct.blue = 0;
+  pf.direct.alphaMask = 0xff;
+  pf.direct.alpha = 24;
+
+  *format = XRenderFindFormat (xdisplay,
+                              (PictFormatType | PictFormatDepth |
+                               PictFormatRedMask | PictFormatRed |
+                               PictFormatGreenMask | PictFormatGreen |
+                               PictFormatBlueMask | PictFormatBlue |
+                               PictFormatAlphaMask | PictFormatAlpha),
+                              &pf,
+                              0);
+  *mask = NULL;
+
+  if (*format)
+    return FORMAT_ARGB;
+
+  return FORMAT_NONE;
+}
+
+#if 0
+static void
+list_formats (XRenderPictFormat *pf)
+{
+  gint i;
+  
+  for (i=0 ;; i++)
+    {
+      XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
+      if (pf)
+       {
+         g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
+                  pf->depth,
+                  pf->direct.red,
+                  pf->direct.redMask,
+                  pf->direct.green,
+                  pf->direct.greenMask,
+                  pf->direct.blue,
+                  pf->direct.blueMask,
+                  pf->direct.alpha,
+                  pf->direct.alphaMask);
+       }
+      else
+       break;
+    }
+}
+#endif  
+
+static void
+convert_to_format (guchar        *src_buf,
+                  gint           src_rowstride,
+                  guchar        *dest_buf,
+                  gint           dest_rowstride,
+                  FormatType     dest_format,
+                  GdkByteOrder   dest_byteorder,
+                  gint           width,
+                  gint           height)
+{
+  gint i;
+
+  if (dest_format == FORMAT_EXACT_MASK &&
+      src_rowstride == dest_rowstride)
+    {
+      memcpy (dest_buf, src_buf, height * src_rowstride);
+      return;
+    }
+  
+  for (i=0; i < height; i++)
+    {
+      switch (dest_format)
+       {
+       case FORMAT_EXACT_MASK:
+         {
+           memcpy (dest_buf + i * dest_rowstride,
+                   src_buf + i * src_rowstride,
+                   width * 4);
+           break;
+         }
+       case FORMAT_ARGB_MASK:
+         {
+           guint *p = (guint *)(src_buf + i * src_rowstride);
+           guint *q = (guint *)(dest_buf + i * dest_rowstride);
+           guint *end = p + width;
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN        
+           if (dest_byteorder == GDK_LSB_FIRST)
+             {
+               /* ABGR => ARGB */
+               
+               while (p < end)
+                 {
+                   *q = ( (*p & 0xff00ff00) |
+                         ((*p & 0x000000ff) << 16) |
+                         ((*p & 0x00ff0000) >> 16));
+                   q++;
+                   p++;
+                 }
+             }
+           else
+             {
+               /* ABGR => BGRA */
+               
+               while (p < end)
+                 {
+                   *q = (((*p & 0xff000000) >> 24) |
+                         ((*p & 0x00ffffff) << 8));
+                   q++;
+                   p++;
+                 }
+             }
+#else /* G_BYTE_ORDER == G_BIG_ENDIAN */
+           if (dest_byteorder == GDK_LSB_FIRST)
+             {
+               /* RGBA => BGRA */
+               
+               while (p < end)
+                 {
+                   *q = ( (*p & 0x00ff00ff) |
+                         ((*p & 0x0000ff00) << 16) |
+                         ((*p & 0xff000000) >> 16));
+                   q++;
+                   p++;
+                 }
+             }
+           else
+             {
+               /* RGBA => ARGB */
+               
+               while (p < end)
+                 {
+                   *q = (((*p & 0xff000000) >> 24) |
+                         ((*p & 0x00ffffff) << 8));
+                   q++;
+                   p++;
+                 }
+             }
+#endif /* G_BYTE_ORDER*/           
+           break;
+         }
+       case FORMAT_ARGB:
+         {
+           guchar *p = (src_buf + i * src_rowstride);
+           guchar *q = (dest_buf + i * dest_rowstride);
+           guchar *end = p + 4 * width;
+           guchar a;
+           guint t;
+           
+#define MULT(d,c,a) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
+           
+           if (dest_byteorder == GDK_LSB_FIRST)
+             {
+               while (p < end)
+                 {
+                   a = p[3];
+                   MULT(q[0], p[2], a);
+                   MULT(q[1], p[1], a);
+                   MULT(q[2], p[0], a);
+                   q[3] = a;
+                   p += 4;
+                   q += 4;
+                 }
+             }
+           else
+             {
+               while (p < end)
+                 {
+                   a = p[3];
+                   q[0] = a;
+                   MULT(q[1], p[0], a);
+                   MULT(q[2], p[1], a);
+                   MULT(q[3], p[2], a);
+                   p += 4;
+                   q += 4;
+                 }
+             }
+#undef MULT
+           break;
+         }
+       case FORMAT_NONE:
+         g_assert_not_reached ();
+         break;
+       }
+    }
+}
+
+static void
+draw_with_images (GdkDrawable       *drawable,
+                 GdkGC             *gc,
+                 FormatType         format_type,
+                 XRenderPictFormat *format,
+                 XRenderPictFormat *mask_format,
+                 guchar            *src_rgb,
+                 gint               src_rowstride,
+                 gint               dest_x,
+                 gint               dest_y,
+                 gint               width,
+                 gint               height)
+{
+  Display *xdisplay = GDK_DRAWABLE_IMPL_X11 (drawable)->xdisplay;
+  GdkImage *image;
+  GdkPixmap *pix;
+  GdkGC *pix_gc;
+  Picture pict;
+  Picture dest_pict;
+  Picture mask = None;
+  gint x0, y0;
+
+  pix = gdk_pixmap_new (NULL, width, height, 32);
+  pict = XRenderCreatePicture (xdisplay, 
+                              GDK_PIXMAP_XID (pix),
+                              format, 0, NULL);
+  if (mask_format)
+    mask = XRenderCreatePicture (xdisplay, 
+                                GDK_PIXMAP_XID (pix),
+                                mask_format, 0, NULL);
+
+  dest_pict = gdk_x11_drawable_get_picture (drawable);
+  
+  pix_gc = gdk_gc_new (pix);
+
+  for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
+    {
+      gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
+      for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
+       {
+         gint xs0, ys0;
+         
+         gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
+         
+         image = _gdk_image_get_scratch (width1, height1, 32, &xs0, &ys0);
+         
+         convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
+                            image->mem + ys0 * image->bpl + 4 * xs0, image->bpl,
+                            format_type, image->byte_order, 
+                            width1, height1);
+
+         gdk_draw_image (pix, pix_gc,
+                         image, xs0, ys0, x0, y0, width1, height1);
+       }
+    }
+  
+  XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
+                   0, 0, 0, 0, dest_x, dest_y, width, height);
+
+  XRenderFreePicture (xdisplay, pict);
+  if (mask)
+    XRenderFreePicture (xdisplay, mask);
+  
+  g_object_unref (pix);
+  g_object_unref (pix_gc);
+}
+
+typedef struct _ShmPixmapInfo ShmPixmapInfo;
+
+struct _ShmPixmapInfo
+{
+  GdkImage *image;
+  Pixmap    pix;
+  Picture   pict;
+  Picture   mask;
+};
+
+/* Returns FALSE if we can't get a shm pixmap */
+static gboolean
+get_shm_pixmap_for_image (Display           *xdisplay,
+                         GdkImage          *image,
+                         XRenderPictFormat *format,
+                         XRenderPictFormat *mask_format,
+                         Pixmap            *pix,
+                         Picture           *pict,
+                         Picture           *mask)
+{
+  ShmPixmapInfo *info;
+  
+  if (image->type != GDK_IMAGE_SHARED)
+    return FALSE;
+  
+  info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
+  if (!info)
+    {
+      *pix = _gdk_x11_image_get_shm_pixmap (image);
+      
+      if (!*pix)
+       return FALSE;
+      
+      info = g_new (ShmPixmapInfo, 1);
+      info->pix = *pix;
+      
+      info->pict = XRenderCreatePicture (xdisplay, info->pix,
+                                        format, 0, NULL);
+      if (mask_format)
+       info->mask = XRenderCreatePicture (xdisplay, info->pix,
+                                          mask_format, 0, NULL);
+      else
+       info->mask = None;
+
+      g_object_set_data (G_OBJECT (image), "gdk-x11-shm-pixmap", info);
+    }
+
+  *pix = info->pix;
+  *pict = info->pict;
+  *mask = info->mask;
+
+  return TRUE;
+}
+
+#ifdef USE_SHM
+/* Returns FALSE if drawing with ShmPixmaps is not possible */
+static gboolean
+draw_with_pixmaps (GdkDrawable       *drawable,
+                  GdkGC             *gc,
+                  FormatType         format_type,
+                  XRenderPictFormat *format,
+                  XRenderPictFormat *mask_format,
+                  guchar            *src_rgb,
+                  gint               src_rowstride,
+                  gint               dest_x,
+                  gint               dest_y,
+                  gint               width,
+                  gint               height)
+{
+  Display *xdisplay = GDK_DRAWABLE_IMPL_X11 (drawable)->xdisplay;
+  GdkImage *image;
+  Pixmap pix;
+  Picture pict;
+  Picture dest_pict;
+  Picture mask = None;
+  gint x0, y0;
+
+  dest_pict = gdk_x11_drawable_get_picture (drawable);
+  
+  for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
+    {
+      gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
+      for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
+       {
+         gint xs0, ys0;
+         
+         gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
+         
+         image = _gdk_image_get_scratch (width1, height1, 32, &xs0, &ys0);
+         if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
+           return FALSE;
+         
+         convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
+                            image->mem + ys0 * image->bpl + 4 * xs0, image->bpl,
+                            format_type, image->byte_order, 
+                            width1, height1);
+
+         XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
+                           xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
+                           width1, height1);
+       }
+    }
+
+  return TRUE;
+}
+#endif
+
+static void
+gdk_x11_draw_pixbuf (GdkDrawable     *drawable,
+                    GdkGC           *gc,
+                    GdkPixbuf       *pixbuf,
+                    gint             src_x,
+                    gint             src_y,
+                    gint             dest_x,
+                    gint             dest_y,
+                    gint             width,
+                    gint             height,
+                    GdkRgbDither     dither,
+                    gint             x_dither,
+                    gint             y_dither)
+{
+  Display *xdisplay = GDK_DRAWABLE_IMPL_X11 (drawable)->xdisplay;
+  FormatType format_type;
+  XRenderPictFormat *format, *mask_format;
+  gint rowstride;
+#ifdef USE_SHM  
+  gboolean use_pixmaps = TRUE;
+#endif /* USE_SHM */
+    
+  format_type = select_format (xdisplay, &format, &mask_format);
+
+  if (format_type == FORMAT_NONE ||
+      !gdk_pixbuf_get_has_alpha (pixbuf) ||
+      (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24))
+    {
+      GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
+      GDK_DRAWABLE_CLASS (parent_class)->_draw_pixbuf (wrapper, gc, pixbuf,
+                                                      src_x, src_y, dest_x, dest_y,
+                                                      width, height,
+                                                      dither, x_dither, y_dither);
+      return;
+    }
+
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+#ifdef USE_SHM  
+  if (use_pixmaps)
+    {
+      if (!draw_with_pixmaps (drawable, gc,
+                             format_type, format, mask_format,
+                             gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
+                             rowstride,
+                             dest_x, dest_y, width, height))
+       use_pixmaps = FALSE;
+    }
+
+  if (!use_pixmaps)
+#endif /* USE_SHM */
+    draw_with_images (drawable, gc,
+                     format_type, format, mask_format,
+                     gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
+                     rowstride,
+                     dest_x, dest_y, width, height);
+}
+#endif /* HAVE_XFT */
index 7412eb726aa7f8d0cf226a3769f9102191fe51f1..b703b7e3b9a5f1de1fe4779275c7de74b653cfc3 100644 (file)
@@ -810,9 +810,13 @@ _gdk_x11_gc_get_fg_picture (GdkGC *gc)
     {
       XRenderPictureAttributes pa;
       XRenderPictFormat *pix_format = foreground_format (gc);
+      Pixmap pix;
 
-      Pixmap pix = XCreatePixmap (x11_gc->xdisplay, _gdk_root_window,
-                                 1, 1, pix_format->depth);
+      if (!pix_format)
+       return None;
+
+      pix = XCreatePixmap (x11_gc->xdisplay, _gdk_root_window,
+                          1, 1, pix_format->depth);
       pa.repeat = True;
       x11_gc->fg_picture = XRenderCreatePicture (x11_gc->xdisplay, 
                                                 pix,
index 21302d7e6f488d8c930b65cd72927ab108cb40d8..4f03ff8de33d30ecd058a3d34735acc597e72d82 100644 (file)
@@ -59,10 +59,12 @@ struct _GdkImagePrivateX11
   XImage *ximage;
   Display *xdisplay;
   gpointer x_shm_info;
+  Pixmap shm_pixmap;
 };
 
 static GList *image_list = NULL;
 static gpointer parent_class = NULL;
+static gboolean have_shm_pixmaps;
 
 static void gdk_x11_image_destroy (GdkImage      *image);
 static void gdk_image_init        (GdkImage      *image);
@@ -198,33 +200,42 @@ _gdk_windowing_image_init (void)
 {
   if (_gdk_use_xshm)
     {
-      if (!gdk_image_check_xshm (gdk_display))
-       {
-         _gdk_use_xshm = False;
-       }
+      gint res = gdk_image_check_xshm (gdk_display);
+
+      if (!res)
+       _gdk_use_xshm = FALSE;
+      else 
+       have_shm_pixmaps = (res == 2);
     }
 }
 
 GdkImage*
-gdk_image_new (GdkImageType  type,
-              GdkVisual    *visual,
-              gint          width,
-              gint          height)
+_gdk_image_new_for_depth (GdkImageType  type,
+                         GdkVisual    *visual,
+                         gint          width,
+                         gint          height,
+                         gint          depth)
 {
   GdkImage *image;
   GdkImagePrivateX11 *private;
 #ifdef USE_SHM
   XShmSegmentInfo *x_shm_info;
 #endif /* USE_SHM */
-  Visual *xvisual;
+  Visual *xvisual = NULL;
 
+  g_return_val_if_fail (!visual || GDK_IS_VISUAL (visual), NULL);
+  g_return_val_if_fail (visual || depth != -1, NULL);
+
+  if (visual)
+    depth = visual->depth;
+  
   switch (type)
     {
     case GDK_IMAGE_FASTEST:
-      image = gdk_image_new (GDK_IMAGE_SHARED, visual, width, height);
+      image = _gdk_image_new_for_depth (GDK_IMAGE_SHARED, visual, width, height, depth);
 
       if (!image)
-       image = gdk_image_new (GDK_IMAGE_NORMAL, visual, width, height);
+       image = _gdk_image_new_for_depth (GDK_IMAGE_NORMAL, visual, width, height, depth);
       break;
 
     default:
@@ -238,9 +249,10 @@ gdk_image_new (GdkImageType  type,
       image->visual = visual;
       image->width = width;
       image->height = height;
-      image->depth = visual->depth;
+      image->depth = depth;
 
-      xvisual = ((GdkVisualPrivate*) visual)->xvisual;
+      if (visual)
+       xvisual = ((GdkVisualPrivate*) visual)->xvisual;
 
       switch (type)
        {
@@ -253,7 +265,7 @@ gdk_image_new (GdkImageType  type,
              x_shm_info->shmid = -1;
              x_shm_info->shmaddr = (char*) -1;
 
-             private->ximage = XShmCreateImage (private->xdisplay, xvisual, visual->depth,
+             private->ximage = XShmCreateImage (private->xdisplay, xvisual, depth,
                                                 ZPixmap, NULL, x_shm_info, width, height);
              if (private->ximage == NULL)
                {
@@ -326,7 +338,7 @@ gdk_image_new (GdkImageType  type,
            goto error;
          break;
        case GDK_IMAGE_NORMAL:
-         private->ximage = XCreateImage (private->xdisplay, xvisual, visual->depth,
+         private->ximage = XCreateImage (private->xdisplay, xvisual, depth,
                                          ZPixmap, 0, 0, width, height, 32, 0);
 
          /* Use malloc, not g_malloc here, because X will call free()
@@ -344,7 +356,7 @@ gdk_image_new (GdkImageType  type,
 
       if (image)
        {
-         image->byte_order = private->ximage->byte_order;
+         image->byte_order = (private->ximage->byte_order == LSBFirst) ? GDK_LSB_FIRST : GDK_MSB_FIRST;
          image->mem = private->ximage->data;
          image->bpl = private->ximage->bytes_per_line;
          image->bpp = (private->ximage->bits_per_pixel + 7) / 8;
@@ -379,39 +391,144 @@ gdk_image_new (GdkImageType  type,
   return NULL;
 }
 
+Pixmap
+_gdk_x11_image_get_shm_pixmap (GdkImage *image)
+{
+  GdkImagePrivateX11 *private = PRIVATE_DATA (image);
+
+#ifdef USE_SHM  
+  /* Future: do we need one of these per-screen per-image? ShmPixmaps
+   * are the same for every screen, but can they be shared?
+   */
+  if (!private->shm_pixmap && image->type == GDK_IMAGE_SHARED && have_shm_pixmaps)
+    private->shm_pixmap = XShmCreatePixmap (private->xdisplay, _gdk_root_window,
+                                           image->mem, private->x_shm_info, 
+                                           image->width, image->height, image->depth);
+
+  return private->shm_pixmap;
+#else
+  return None;
+#endif    
+}
+
 GdkImage*
-_gdk_x11_get_image (GdkDrawable    *drawable,
-                    gint            x,
-                    gint            y,
-                    gint            width,
-                    gint            height)
+gdk_image_new (GdkImageType  type,
+              GdkVisual    *visual,
+              gint          width,
+              gint          height)
+{
+  return _gdk_image_new_for_depth (type, visual, width, height, -1);
+}
+
+GdkImage*
+get_full_image (GdkDrawable    *drawable,
+               gint            src_x,
+               gint            src_y,
+               gint            width,
+               gint            height)
 {
   GdkImage *image;
+  GdkImagePrivateX11 *private;
+  GdkDrawableImplX11 *impl;
+  XImage *ximage;
+
+  impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  
+  ximage = XGetImage (impl->xdisplay,
+                     impl->xid,
+                     src_x, src_y, width, height,
+                     AllPlanes, ZPixmap);
+  
+  if (!ximage)
+    return NULL;
+  
+  image = g_object_new (gdk_image_get_type (), NULL);
+  
+  private = PRIVATE_DATA (image);
+  
+  private->xdisplay = gdk_display;
+  private->ximage = ximage;
+  
+  image->type = GDK_IMAGE_NORMAL;
+  image->visual = gdk_drawable_get_visual (drawable); /* could be NULL */
+  image->width = width;
+  image->height = height;
+  image->depth = gdk_drawable_get_depth (drawable);
+  
+  image->mem = private->ximage->data;
+  image->bpl = private->ximage->bytes_per_line;
+  image->bits_per_pixel = private->ximage->bits_per_pixel;
+  image->bpp = (private->ximage->bits_per_pixel + 7) / 8;
+  image->byte_order = (private->ximage->byte_order == LSBFirst) ? GDK_LSB_FIRST : GDK_MSB_FIRST;
+  
+  return image;
+}
+
+GdkImage*
+_gdk_x11_copy_to_image (GdkDrawable    *drawable,
+                       GdkImage       *image,
+                       gint            src_x,
+                       gint            src_y,
+                       gint            dest_x,
+                       gint            dest_y,
+                       gint            width,
+                       gint            height)
+{
   GdkImagePrivateX11 *private;
   GdkDrawableImplX11 *impl;
   GdkVisual *visual;
   gboolean have_grab;
   GdkRectangle req;
   GdkRectangle window_rect;
-  XImage *ximage;
+  Pixmap shm_pixmap = None;
+  gboolean success = TRUE;
   
   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_X11 (drawable), NULL);
+  g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL);
 
   visual = gdk_drawable_get_visual (drawable);
-
-  g_assert (visual || !GDK_IS_WINDOW_IMPL_X11 (drawable));
-
   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
   
   have_grab = FALSE;
 
+#define UNGRAB() G_STMT_START {                        \
+    if (have_grab) {                           \
+      gdk_x11_ungrab_server ();                        \
+      XFlush (impl->xdisplay);                 \
+      have_grab = FALSE; }                     \
+  } G_STMT_END
+
+  if (!image && !GDK_IS_WINDOW_IMPL_X11 (drawable))
+    return get_full_image (drawable, src_x, src_y, width, height);
+
+  if (image && image->type == GDK_IMAGE_SHARED)
+    {
+      shm_pixmap = _gdk_x11_image_get_shm_pixmap (image);
+      if (shm_pixmap)
+       {
+         /* Again easy, we can just XCopyArea, and don't have to worry about clipping
+          */
+         GC xgc = XCreateGC (impl->xdisplay, impl->xid, 0, NULL);
+         
+         XCopyArea (impl->xdisplay, impl->xid, shm_pixmap, xgc,
+                    src_x, src_y, width, height, dest_x, dest_y);
+         XSync (impl->xdisplay, FALSE);
+         
+         XFreeGC (impl->xdisplay, xgc);
+         
+         return image;
+       }
+    }
+
+  /* Now the general case - we may have to worry about clipping to the screen
+   * bounds, in which case we'll have to grab the server and only get a piece
+   * of the window.
+   */
   if (GDK_IS_WINDOW_IMPL_X11 (drawable))
     {
       GdkRectangle screen_rect;
       Window child;
 
-      g_assert (visual);
-
       have_grab = TRUE;
       gdk_x11_grab_server ();
 
@@ -443,13 +560,7 @@ _gdk_x11_get_image (GdkDrawable    *drawable,
       if (gdk_error_trap_pop () ||
           !gdk_rectangle_intersect (&window_rect, &screen_rect, 
                                     &window_rect))
-        {
-          if (have_grab)
-            gdk_x11_ungrab_server ();
-          return image = gdk_image_new (GDK_IMAGE_FASTEST,
-                                        visual,
-                                        width, height);
-        }
+       goto out;
     }
   else
     {
@@ -460,8 +571,8 @@ _gdk_x11_get_image (GdkDrawable    *drawable,
                             &window_rect.height);
     }
       
-  req.x = x;
-  req.y = y;
+  req.x = src_x;
+  req.y = src_y;
   req.width = width;
   req.height = height;
   
@@ -470,97 +581,66 @@ _gdk_x11_get_image (GdkDrawable    *drawable,
    * For pixmaps this is all of the pixmap, for windows it is just 
    * the onscreen part.
    */
-  if (!gdk_rectangle_intersect (&req, &window_rect, &req) && visual) 
-    {      
-      if (have_grab)
-       gdk_x11_ungrab_server ();
-      return image = gdk_image_new (GDK_IMAGE_FASTEST,
-                                    visual,
-                                    width, height);
-    }
-
-  if (req.x != x || req.y != y)
-    {
-      g_assert (GDK_IS_WINDOW (drawable));
-      g_assert (visual);
-
-      image = gdk_image_new (GDK_IMAGE_FASTEST,
-                             visual,
-                             width, height);
-      if (image == NULL)
-        {
-          if (have_grab)
-            gdk_x11_ungrab_server ();
-          return NULL;
-        }
-
-      private = PRIVATE_DATA (image);
+  if (!gdk_rectangle_intersect (&req, &window_rect, &req))
+    goto out;
 
-      gdk_error_trap_push ();
-
-      ximage = XGetSubImage (impl->xdisplay,
-                             impl->xid,
-                             req.x, req.y, req.width, req.height,
-                             AllPlanes, ZPixmap,
-                             private->ximage,
-                             req.x - x, req.y - y);
-
-      if (have_grab)
-        {
-          gdk_x11_ungrab_server ();
-          have_grab = FALSE;
-        }
-      
-      if (gdk_error_trap_pop () || ximage == NULL)
-        {
-          g_object_unref (G_OBJECT (image));
-          return NULL;
-        }
+  private = PRIVATE_DATA (image);
 
-      g_assert (ximage == private->ximage);
+  gdk_error_trap_push ();
+  
+  if (!image &&
+      req.x == src_x && req.y == src_y && req.width == width && req.height == height)
+    {
+      image = get_full_image (drawable, src_x, src_y, width, height);
+      if (!image)
+       success = FALSE;
     }
   else
     {
-      /* Here we ignore the req.width, req.height -
-       * XGetImage() will do the right thing without
-       * them.
-       */
-      ximage = XGetImage (impl->xdisplay,
-                          impl->xid,
-                          x, y, width, height,
-                          AllPlanes, ZPixmap);
-
-      if (have_grab)
-        {
-          gdk_x11_ungrab_server ();
-          have_grab = FALSE;
-        }      
-
-      if (!ximage)
-        return NULL;
-
-      image = g_object_new (gdk_image_get_type (), NULL);
-
-      private = PRIVATE_DATA (image);
-
-      private->xdisplay = gdk_display;
-      private->ximage = ximage;
-
-      image->type = GDK_IMAGE_NORMAL;
-      image->visual = visual; /* May be NULL */
-      image->width = width;
-      image->height = height;
-      image->depth = gdk_drawable_get_depth (drawable);
+      gboolean created_image = FALSE;
+      
+      if (!image)
+       {
+         image = _gdk_image_new_for_depth (GDK_IMAGE_NORMAL, visual, width, height,
+                                           gdk_drawable_get_depth (drawable));
+         created_image = TRUE;
+       }
 
-      image->mem = private->ximage->data;
-      image->bpl = private->ximage->bytes_per_line;
-      image->bits_per_pixel = private->ximage->bits_per_pixel;
-      image->bpp = (private->ximage->bits_per_pixel + 7) / 8;
-      image->byte_order = private->ximage->byte_order; 
+      /* In the ShmImage but no ShmPixmap case, we could use XShmGetImage when
+       * we are getting the entire image.
+       */
+      if (XGetSubImage (impl->xdisplay,
+                       impl->xid,
+                       req.x, req.y, req.width, req.height,
+                       AllPlanes, ZPixmap,
+                       private->ximage,
+                       dest_x + req.x - src_x, dest_y + req.y - src_y) == None)
+       {
+         if (created_image)
+           g_object_unref (image);
+         image = NULL;
+         success = FALSE;
+       }
     }
 
-  g_assert (!have_grab);
+ out:
+  
+  if (have_grab)
+    {                          
+      gdk_x11_ungrab_server ();
+      XFlush (impl->xdisplay);
+      have_grab = FALSE;
+    }
   
+  gdk_error_trap_pop ();
+
+  if (success && !image)
+    {
+      /* We "succeeded", but could get no content for the image so return junk */
+      image = _gdk_image_new_for_depth (GDK_IMAGE_NORMAL, visual, width, height,
+                                       gdk_drawable_get_depth (drawable));
+    }
+      
   return image;
 }
 
@@ -625,7 +705,11 @@ gdk_x11_image_destroy (GdkImage *image)
        case GDK_IMAGE_SHARED:
 #ifdef USE_SHM
          gdk_flush();
-         
+
+         if (private->shm_pixmap)
+           XFreePixmap (private->xdisplay, private->shm_pixmap);
+                 
+         image_list = g_list_remove (image_list, image);
          XShmDetach (private->xdisplay, private->x_shm_info);
          XDestroyImage (private->ximage);
          
@@ -634,8 +718,7 @@ gdk_x11_image_destroy (GdkImage *image)
          
          g_free (private->x_shm_info);
          private->x_shm_info = NULL;
-         
-         image_list = g_list_remove (image_list, image);
+
 #else /* USE_SHM */
          g_error ("trying to destroy shared memory image when gdk was compiled without shared memory support");
 #endif /* USE_SHM */
@@ -673,3 +756,23 @@ gdk_x11_image_get_ximage (GdkImage *image)
 
   return private->ximage;
 }
+
+gint
+_gdk_windowing_get_bits_for_depth (gint depth)
+{
+  XPixmapFormatValues *formats;
+  gint count, i;
+  
+  formats = XListPixmapFormats (gdk_display, &count);
+  
+  for (i = 0; i < count; i++)
+    if (formats[i].depth == depth)
+      {
+       gint result = formats[i].bits_per_pixel;
+       XFree (formats);
+       return result;
+      }
+
+  g_assert_not_reached ();
+  return -1;
+}
index 411bf01b2c4e90c31eef5fa227736406f53ec5e2..a823cf96a82817dc7c7ee277b650a2390520a400 100644 (file)
@@ -49,7 +49,7 @@ gdk_pango_context_get (void)
     {
       const char *val = g_getenv ("GDK_USE_XFT");
 
-      use_xft = val && (atoi (val) != 0);
+      use_xft = val && (atoi (val) != 0) && _gdk_x11_have_render ();
     }
   
   if (use_xft)
index 6552ff5383c55a25c242228b9353010396b6a081..a495c518784620ae239aebf859d5d43b97868d65 100644 (file)
@@ -100,7 +100,8 @@ gint          gdk_send_xevent          (Window           window,
 GType _gdk_gc_x11_get_type (void);
 
 #ifdef HAVE_XFT
-Picture _gdk_x11_gc_get_fg_picture     (GdkGC            *gc);
+gboolean _gdk_x11_have_render       (void);
+Picture  _gdk_x11_gc_get_fg_picture (GdkGC *gc);
 #endif /* HAVE_XFT */
 
 GdkGC *_gdk_x11_gc_new                  (GdkDrawable     *drawable,
@@ -112,11 +113,15 @@ GdkVisual *   gdk_visual_lookup        (Visual          *xvisual);
 
 void gdk_window_add_colormap_windows (GdkWindow *window);
 
-GdkImage* _gdk_x11_get_image (GdkDrawable    *drawable,
-                              gint            x,
-                              gint            y,
-                              gint            width,
-                              gint            height);
+GdkImage *_gdk_x11_copy_to_image       (GdkDrawable *drawable,
+                                       GdkImage    *image,
+                                       gint         src_x,
+                                       gint         src_y,
+                                       gint         dest_x,
+                                       gint         dest_y,
+                                       gint         width,
+                                       gint         height);
+Pixmap   _gdk_x11_image_get_shm_pixmap (GdkImage    *image);
 
 /* Please see gdkwindow.c for comments on how to use */ 
 Window gdk_window_xid_at        (Window    base,
index 12f088f605192632d51c906e98f4f89ae546da39..9a61f92f88d4ac779325910202ecbb39fd181dc8 100644 (file)
@@ -48,7 +48,7 @@ quit_func (GtkWidget *widget, gpointer dummy)
 
 #define WIDTH 640
 #define HEIGHT 400
-#define NUM_ITERS 100
+#define NUM_ITERS 50
 
 static void
 testrgb_rgb_test (GtkWidget *drawing_area)
@@ -62,11 +62,13 @@ testrgb_rgb_test (GtkWidget *drawing_area)
   gboolean dither;
   int dith_max;
   GTimer *timer;
-
-  buf = g_malloc (WIDTH * HEIGHT * 6);
+  GdkPixbuf *pixbuf;
+  gboolean to_pixmap;
+  
+  buf = g_malloc (WIDTH * HEIGHT * 8);
 
   val = 0;
-  for (j = 0; j < WIDTH * HEIGHT * 6; j++)
+  for (j = 0; j < WIDTH * HEIGHT * 8; j++)
     {
       val = (val + ((val + (rand () & 0xff)) >> 1)) >> 1;
       buf[j] = val;
@@ -103,6 +105,7 @@ testrgb_rgb_test (GtkWidget *drawing_area)
                              GDK_RGB_DITHER_NONE,
                              buf + offset, WIDTH * 3);
        }
+      gdk_flush ();
       total_time = g_timer_elapsed (timer, NULL) - start_time;
       g_print ("Color test%s time elapsed: %.2fs, %.1f fps, %.2f megapixels/s\n",
               dither ? " (dithered)" : "",
@@ -124,6 +127,7 @@ testrgb_rgb_test (GtkWidget *drawing_area)
                               GDK_RGB_DITHER_NONE,
                               buf + offset, WIDTH);
        }
+      gdk_flush ();
       total_time = g_timer_elapsed (timer, NULL) - start_time;
       g_print ("Grayscale test%s time elapsed: %.2fs, %.1f fps, %.2f megapixels/s\n",
               dither ? " (dithered)" : "",
@@ -132,6 +136,42 @@ testrgb_rgb_test (GtkWidget *drawing_area)
               NUM_ITERS * (WIDTH * HEIGHT * 1e-6) / total_time);
     }
 
+  for (to_pixmap = FALSE; to_pixmap <= TRUE; to_pixmap++)
+    {
+      if (to_pixmap)
+       {
+         GdkRectangle rect = { 0, 0, WIDTH, HEIGHT };
+         gdk_window_begin_paint_rect (drawing_area->window, &rect);
+       }
+       
+      start_time = g_timer_elapsed (timer, NULL);
+      for (i = 0; i < NUM_ITERS; i++)
+       {
+         offset = (rand () % (WIDTH * HEIGHT * 4)) & -4;
+         pixbuf = gdk_pixbuf_new_from_data (buf + offset, GDK_COLORSPACE_RGB, TRUE,
+                                            8, WIDTH, HEIGHT, WIDTH * 4,
+                                            NULL, NULL);
+         gdk_pixbuf_render_to_drawable_alpha (pixbuf, drawing_area->window,
+                                              0, 0, 0, 0, WIDTH, HEIGHT,
+                                              GDK_PIXBUF_ALPHA_FULL, /* ignored */
+                                              0x80, /* ignored */
+                                              GDK_RGB_DITHER_NORMAL,
+                                              0, 0);
+         gdk_pixbuf_unref (pixbuf);
+       }
+      gdk_flush ();
+      total_time = g_timer_elapsed (timer, NULL) - start_time;
+
+      if (to_pixmap)
+       gdk_window_end_paint (drawing_area->window);
+      
+      g_print ("Alpha test%s time elapsed: %.2fs, %.1f fps, %.2f megapixels/s\n",
+              to_pixmap ? " (to pixmap)" : "",
+              total_time,
+              NUM_ITERS / total_time,
+              NUM_ITERS * (WIDTH * HEIGHT * 1e-6) / total_time);
+    }
+      
   g_print ("Please submit these results to http://www.levien.com/gdkrgb/survey.html\n");
 
 #if 1